bzoj 4519: [Cqoi2016]不同的最小割 最小割树
怎么求一张无向图中任意两点之间的最小割?
http://fanhq666.blog.163.com/blog/static/8194342620113495335724/
一张无向图不同的最小割最多有n-1个。
所以可以用这些最小割建出一棵最小割树。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<queue> 6 #define inf 0x3f3f3f3f 7 #define N 855 8 #define M 400005 9 using namespace std; 10 int read() 11 { 12 int p=0;char c=getchar(); 13 while(c<'0'||c>'9')c=getchar(); 14 while(c>='0'&&c<='9')p=p*10+c-'0',c=getchar(); 15 return p; 16 } 17 int head[N],ver[M],nxt[M],f[M],tot,ch[N]; 18 void add(int a,int b,int c) 19 { 20 tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;f[tot]=c;return ; 21 } 22 queue<int>q;int S,T; 23 bool tell() 24 { 25 memset(ch,-1,sizeof(ch)); 26 q.push(S);ch[S]=0; 27 while(!q.empty()) 28 { 29 int tmp=q.front();q.pop(); 30 for(int i=head[tmp];i;i=nxt[i]) 31 { 32 if(f[i]&&ch[ver[i]]==-1) 33 { 34 ch[ver[i]]=ch[tmp]+1; 35 q.push(ver[i]); 36 } 37 } 38 } 39 return ch[T]!=-1; 40 } 41 int zeng(int a,int b) 42 { 43 if(a==T)return b; 44 int r=0; 45 for(int i=head[a];i&&b>r;i=nxt[i]) 46 { 47 if(f[i]&&ch[ver[i]]==ch[a]+1) 48 { 49 int t=zeng(ver[i],min(f[i],b-r)); 50 f[i]-=t;f[i^1]+=t;r+=t; 51 } 52 } 53 if(!r)ch[a]=-1; 54 return r; 55 } 56 int dinic() 57 { 58 int r=0,t; 59 while(tell())while(t=zeng(S,inf))r+=t; 60 return r; 61 } 62 void hui() 63 { 64 for(int i=2;i<=tot;i+=2) 65 { 66 f[i]=f[i^1]=(f[i]+f[i^1])>>1; 67 }return ; 68 } 69 int tim; 70 int c[N]; 71 void dfs(int x) 72 { 73 c[x]=tim; 74 for(int i=head[x];i;i=nxt[i]) 75 { 76 if(f[i]&&c[ver[i]]!=tim)dfs(ver[i]); 77 } 78 return ; 79 } 80 int p[N]; 81 int ans[N],cnt; 82 int n,m; 83 int st[N],st2[N]; 84 void solve(int l,int r) 85 { 86 if(l==r)return ; 87 hui(); 88 S=p[l];T=p[r]; 89 int tmp=dinic(); 90 tim++;dfs(S); 91 ans[++cnt]=tmp; 92 int top1=0,top2=0; 93 for(int i=l;i<=r;i++) 94 { 95 if(c[p[i]]==tim)st[++top1]=p[i]; 96 else st2[++top2]=p[i]; 97 } 98 for(int i=l;i<=l+top1-1;i++)p[i]=st[i-l+1]; 99 for(int i=l+top1;i<=r;i++)p[i]=st2[i-l-top1+1]; 100 solve(l,l+top1-1);solve(l+top1,r); 101 } 102 int main() 103 { 104 scanf("%d%d",&n,&m); 105 int t1,t2,t3;tot=1; 106 for(int i=1;i<=m;i++) 107 { 108 t1=read();t2=read();t3=read(); 109 add(t1,t2,t3);add(t2,t1,t3); 110 } 111 for(int i=1;i<=n;i++)p[i]=i; 112 solve(1,n); 113 sort(ans+1,ans+cnt+1); 114 int as=0; 115 for(int i=1;i<=cnt;i++) 116 { 117 if(i==1||ans[i]!=ans[i-1]) 118 { 119 as++; 120 } 121 } 122 printf("%d\n",as); 123 }