cf786E ALT (最小割+倍增优化建图)
Posted ressed
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cf786E ALT (最小割+倍增优化建图)相关的知识,希望对你有一定的参考价值。
如果把“我全都要”看作是我全不要的话,就可以用最小割解决啦
源点S,汇点T
我们试图让每个市民作为一个等待被割断的路径
把狗狗给市民:建边(S,i,1),其中i是市民
把狗狗给守卫:建边(j,T,1),其中j是守卫(也就是边)
市民要在路上所有边看到狗:建边(i,j,1),其中i是市民,j是i经过的边
(众所周知,(!A)&(!B)==!(A|B),所以要把两种选择串起来)
然而这样边数太多了,考虑倍增来优化建边
...反正就是倍增优化建边,流量给正无穷
最大流=最小割,跑个dinic就行了(要加当前弧优化不然会T)
然后考虑输出方案。一个边如果被割断了,那么它的残余容量就是0
所以我们来从Sdfs一下,如果能搜到某个人,说明他没有狗;如果能搜到某条边,又因为S和T不连通,说明这条边到T要被割断,说明它有狗
各种各样的数组开大一点又不会怀孕
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=2e4+10,inf=0x3f3f3f3f; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<‘0‘||c>‘9‘){if(c==‘-‘) neg=-1;c=getchar();} 11 while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar(); 12 return x*neg; 13 } 14 15 struct Edge{ 16 int b,l,ne; 17 }ek[maxn*100]; 18 int N,M,ekh[maxn*50],kct=1; 19 int egh[maxn],eg[maxn*2][2],ect=1; 20 int dep[maxn*40],fa[maxn][20],id[maxn][20],pct=2; 21 int S=1,T=2,P[maxn]; 22 int A[maxn],cur[maxn*40]; 23 bool flag[maxn*40],B[maxn]; 24 queue<int> q; 25 26 inline void adeg(int a,int b){ 27 eg[++ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect; 28 } 29 inline void adek(int a,int b,int c){ 30 // printf("!%d %d %d ",a,b,c); 31 ek[++kct].b=b,ek[kct].l=c,ek[kct].ne=ekh[a],ekh[a]=kct; 32 ek[++kct].b=a,ek[kct].l=0,ek[kct].ne=ekh[b],ekh[b]=kct; 33 } 34 35 void dfs(int x){ 36 for(int i=0;fa[x][i]&&fa[fa[x][i]][i];i++){ 37 fa[x][i+1]=fa[fa[x][i]][i]; 38 id[x][i+1]=++pct; 39 adek(id[x][i+1],id[x][i],inf); 40 adek(id[x][i+1],id[fa[x][i]][i],inf); 41 } 42 for(int i=egh[x];i;i=eg[i][1]){ 43 int b=eg[i][0]; 44 if(b==fa[x][0]) continue; 45 fa[b][0]=x;dep[b]=dep[x]+1; 46 id[b][0]=++pct;adek(id[b][0],T,1); 47 // printf("~%d %d ",b,id[b][0]); 48 dfs(b); 49 } 50 } 51 52 void buildlca(int x,int y,int p){ 53 if(dep[x]<dep[y]) swap(x,y); 54 for(int i=log2(dep[x]-dep[y]);i>=0&&dep[x]!=dep[y];i--){ 55 if(dep[fa[x][i]]>=dep[y]){ 56 adek(p,id[x][i],1); 57 x=fa[x][i]; 58 } 59 } 60 if(x==y) return; 61 for(int i=log2(dep[x]);i>=0;i--){ 62 if(fa[x][i]!=fa[y][i]){ 63 adek(p,id[x][i],1);adek(p,id[y][i],1); 64 x=fa[x][i],y=fa[y][i]; 65 } 66 } 67 adek(p,id[x][0],1);adek(p,id[y][0],1); 68 69 } 70 71 bool bfs(){ 72 CLR(dep,0);CLR(cur,-1); 73 dep[S]=1;q.push(S); 74 while(!q.empty()){ 75 int p=q.front();q.pop(); 76 // printf("[email protected]#%d %d ",p,dep[p]); 77 for(int i=ekh[p];i;i=ek[i].ne){ 78 int b=ek[i].b; 79 if(dep[b]||!ek[i].l) continue; 80 dep[b]=dep[p]+1; 81 q.push(b); 82 } 83 } 84 return dep[T]; 85 } 86 87 int dinic(int x,int y){ 88 if(x==T) return y; 89 int tmp=y; 90 if(cur[x]==-1) cur[x]=ekh[x]; 91 for(int &i=cur[x];i;i=ek[i].ne){ 92 // printf("%d %d ",i,cur[x]); 93 int b=ek[i].b; 94 if(dep[b]!=dep[x]+1||!ek[i].l) continue; 95 int re=dinic(b,min(ek[i].l,tmp)); 96 ek[i].l-=re,ek[i^1].l+=re; 97 tmp-=re;if(!tmp) break; 98 }return y-tmp; 99 } 100 101 void getans(int x){ 102 flag[x]=1; 103 for(int i=ekh[x];i;i=ek[i].ne){ 104 int b=ek[i].b; 105 if(!ek[i].l) continue; 106 if(!flag[b]) getans(b); 107 } 108 } 109 110 int main(){ 111 // freopen("768E.in","r",stdin); 112 int i,j,k; 113 N=rd(),M=rd(); 114 for(i=1;i<N;i++){ 115 int a=rd(),b=rd(); 116 adeg(a,b);adeg(b,a); 117 } 118 for(i=1;i<=M;i++) P[i]=++pct; 119 dep[1]=1;dfs(1); 120 for(i=1;i<=M;i++){ 121 int a=rd(),b=rd(); 122 adek(S,P[i],1); 123 buildlca(a,b,P[i]); 124 } 125 int ans=0,a=0,b=0; 126 while(bfs()) ans+=dinic(S,inf); 127 getans(S); 128 for(i=3;i<=M+2;i++) 129 if(!flag[i]) A[++a]=i-2; 130 for(i=2;i<=N;i++) 131 if(flag[id[i][0]]) B[i]=1,b++; 132 printf("%d %d ",ans,a); 133 for(i=1;i<=a;i++) 134 printf("%d ",A[i]); 135 printf(" %d ",b); 136 for(i=1;i<N;i++){ 137 int x=eg[i<<1][0],y=eg[i<<1|1][0]; 138 if(fa[x][0]!=y) swap(x,y); 139 // printf("!%d %d! ",x,y); 140 if(B[x]) printf("%d ",i); 141 } 142 143 return 0; 144 }
以上是关于cf786E ALT (最小割+倍增优化建图)的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj3218] a+b problem [最小割+数据结构优化建图]
[XSY 1129] flow 最小割 树链剖分 线段树优化建图