bzoj4519: [Cqoi2016]不同的最小割(分治最小割)
Posted CHerish_OI
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4519: [Cqoi2016]不同的最小割(分治最小割)相关的知识,希望对你有一定的参考价值。
4519: [Cqoi2016]不同的最小割
题目:传送门
题解:
基本一样的题目啊,就最后用set记录一下就ok
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #include<set> 7 using namespace std; 8 const int inf=999999999; 9 struct node 10 { 11 int x,y,c,next,other; 12 }a[210000];int len,last[110000]; 13 int st,ed,n,m,T,ans; 14 void ins(int x,int y,int c) 15 { 16 int k1,k2; 17 k1=++len; 18 a[len].x=x;a[len].y=y;a[len].c=c; 19 a[len].next=last[x];last[x]=len; 20 21 k2=++len; 22 a[len].x=y;a[len].y=x;a[len].c=c; 23 a[len].next=last[y];last[y]=len; 24 25 a[k1].other=k2; 26 a[k2].other=k1; 27 } 28 int list[110000],h[110000],head,tail; 29 bool bt_h() 30 { 31 memset(h,0,sizeof(h));h[st]=1; 32 list[1]=st;head=1;tail=2; 33 while(head!=tail) 34 { 35 int x=list[head]; 36 for(int k=last[x];k;k=a[k].next) 37 { 38 int y=a[k].y; 39 if(h[y]==0 && a[k].c) 40 { 41 h[y]=h[x]+1; 42 list[tail++]=y; 43 } 44 } 45 head++; 46 } 47 if(h[ed])return true; 48 return false; 49 } 50 int find_flow(int x,int flow) 51 { 52 if(x==ed)return flow; 53 int s=0,t; 54 for(int k=last[x];k;k=a[k].next) 55 { 56 int y=a[k].y; 57 if(h[y]==h[x]+1 && a[k].c && s<flow) 58 { 59 s+=t=find_flow(y,min(a[k].c,flow-s)); 60 a[k].c-=t;a[a[k].other].c+=t; 61 } 62 } 63 if(s==0)h[x]=0; 64 return s; 65 } 66 int d[110000],num[110000],sta[110000],anss[1100][1100]; 67 void re_num(int x) 68 { 69 num[x]=1; 70 for(int k=last[x];k;k=a[k].next) 71 { 72 int y=a[k].y; 73 if(a[k].c && !num[y]) 74 re_num(y); 75 } 76 } 77 void solve(int l,int r) 78 { 79 if(l==r)return ; 80 for(int i=1;i<=len;i+=2)a[i].c=a[i+1].c=(a[i].c+a[i+1].c)>>1; 81 st=d[l];ed=d[r];ans=0; 82 while(bt_h())ans+=find_flow(st,inf); 83 memset(num,0,sizeof(num)); 84 re_num(st); 85 for(int i=1;i<=n;i++) 86 if(num[i]) 87 for(int j=1;j<=n;j++) 88 if(!num[j]) 89 anss[i][j]=anss[j][i]=min(anss[i][j],ans); 90 int L=l,R=r; 91 for(int i=l;i<=r;i++) 92 { 93 if(num[d[i]])sta[L++]=d[i]; 94 else sta[R--]=d[i]; 95 } 96 for(int i=l;i<=r;i++)d[i]=sta[i]; 97 solve(l,L-1);solve(R+1,r); 98 } 99 set<int> q; 100 set<int> :: iterator it; 101 int main() 102 { 103 scanf("%d%d",&n,&m); 104 len=0;memset(last,0,sizeof(last));int x,y,c; 105 for(int i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&c),ins(x,y,c); 106 for(int i=1;i<=n;i++)d[i]=i;memset(anss,63,sizeof(anss)); 107 solve(1,n); 108 for(int i=1;i<=n;i++) 109 for(int j=i+1;j<=n;j++) 110 q.insert(anss[i][j]); 111 printf("%d\\n",q.size()); 112 return 0; 113 }
以上是关于bzoj4519: [Cqoi2016]不同的最小割(分治最小割)的主要内容,如果未能解决你的问题,请参考以下文章