之前没看懂题意就把这题扔了,现在一看是读错题意了
简化版题意
给出一颗树(这个图的最短路径生成树),每个点初始颜色为\(0\)
两种操作:
将部分点颜色取反
给出一些点,建出虚树(边权为两点树上距离),求最小割边代价使得虚树上没有颜色为\(1\)的点与根联通
那这就很模板了:
设\(f[x]\)表示\(x\)子树的答案,\(c[x]\)表示\(x\)的颜色,则有转移方程:(当\(f[K]=0\)时输出\(-1\))
\[
f[x]+=Val(x,y)\quad (c[y]=1)\\
f[x]+=\min (Val(x,y),f[y])\quad (c[y]=0)
\]
(注意以上方法没有考虑边权全为\(0\)但是答案不为\(-1\)的情况,不过好像没有这种数据,反正也不难特判就没管了)
时间复杂度 \(O((N+M)\log N+Qnum(\log num+\log N))\)
(数据为什么这么小)
代码:
#include <queue> #include <cstdio> #include <cctype> #include <vector> #include <cstring> #include <algorithm> inline char Getchar() { static char In[1<<22],*p1=In,*p2=In; return p1==p2&&(p2=(p1=In)+fread(In,1,1<<22,stdin),p1==p2)?EOF:*p1++; } inline int Getint() { int x=0,c; while(!isdigit(c=Getchar())); for(;isdigit(c);c=Getchar())x=x*10+(c^48); return x; } const int N=50005,Inf=0x7f7f7f7f; int n,M,K,Q,Dis[N],Pre[N]; int Dfn[N],Tim,Dep[N],f[N][16]; int c[N],a[N],s[N],Top; std::vector<int> G[N],Gv[N],T[N],V[N]; //Graph|Graph Value|Tree|Virtual Tree void Dijkstra() { struct Rec{int x,d;inline bool operator<(const Rec& o)const{return d>o.d;}}; std::priority_queue<Rec> q; memset(Dis,0x7f,sizeof Dis); q.push((Rec){K,Dis[K]=0}); while(!q.empty()) { int x=q.top().x,d=q.top().d; if(q.pop(),d!=Dis[x])continue; for(int i=0,y,v;i<(int)G[x].size();++i) if(Dis[y=G[x][i]]>Dis[x]+(v=Gv[x][i])||(Dis[y]==Dis[x]+v&&x<Pre[y])) q.push((Rec){y,Dis[y]=Dis[x]+v}),Pre[y]=x; } for(int i=1;i<=n;++i)if(i!=K)T[Pre[i]].push_back(i); } void DFS(int x,int Fa) { Dfn[x]=++Tim,Dep[x]=Dep[f[x][0]=Fa]+1; for(int i=1;i<=15;++i)f[x][i]=f[f[x][i-1]][i-1]; for(auto y:T[x])if(y!=Fa)DFS(y,x); } int Lca(int x,int y) { if(Dep[x]<Dep[y])std::swap(x,y); for(int i=15;i>=0;--i)if(Dep[f[x][i]]>=Dep[y])x=f[x][i]; if(x==y)return y; for(int i=15;i>=0;--i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[y][0]; } int DP(int x) { int Res=0; for(auto y:V[x]) { int v=DP(y); if(c[y])Res+=Dis[y]-Dis[x]; else Res+=std::min(v,Dis[y]-Dis[x]); } V[x].clear(); return Res; } int main() { //freopen("in.txt","r",stdin); n=Getint(),M=Getint(),K=Getint(),Q=Getint(); for(int i=1,x,y,z;i<=M;++i) { x=Getint(),y=Getint(),z=Getint(); G[x].push_back(y),Gv[x].push_back(z); G[y].push_back(x),Gv[y].push_back(z); } Dijkstra(),DFS(K,0); for(int o,k;Q--;) if(o=Getint(),k=Getint(),!o)while(k--)c[Getint()]^=1; else { for(int i=1;i<=k;++i)a[i]=Getint(); s[Top=1]=K,std::sort(a+1,a+k+1,[](int x,int y){return Dfn[x]<Dfn[y];}); for(int i=1;i<=k;++i) { int Ls=Lca(s[Top],a[i]); while(Top>1&&Dfn[s[Top-1]]>=Dfn[Ls])V[s[Top-1]].push_back(s[Top]),--Top; if(s[Top]!=Ls)V[Ls].push_back(s[Top]),s[Top]=Ls; s[++Top]=a[i]; } while(Top>1)V[s[Top-1]].push_back(s[Top]),--Top; int Ans=DP(K); printf("%d\n",Ans?Ans:-1); } return 0; }
来源:https://www.cnblogs.com/LanrTabe/p/12173581.html