[bzoj2561]最小生成树
考虑一条边被选入最小生成树的条件,即所有比他小的边不能让这条边所连接的两个点连通,那么将所有边建成两条有向边并跑这两个点的最小割即可(最大生成树同理,但不可以一起做)。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 20005 4 #define inf 0x3f3f3f3f 5 struct ji{ 6 int nex,to,len; 7 }edge[N*40]; 8 struct ji2{ 9 int x,y,z; 10 bool operator < (const ji2 &k)const{ 11 return z<k.z; 12 } 13 }a[N*10]; 14 queue<int>q; 15 int E,n,m,x,y,head[N],work[N],d[N]; 16 void add(int x,int y,int z){ 17 edge[E].nex=head[x]; 18 edge[E].to=y; 19 edge[E].len=z; 20 head[x]=E++; 21 if (E&1)add(y,x,0); 22 } 23 bool bfs(){ 24 memset(d,-1,sizeof(d)); 25 q.push(a[0].x); 26 d[a[0].x]=0; 27 while (!q.empty()){ 28 int k=q.front(); 29 q.pop(); 30 for(int i=head[k];i!=-1;i=edge[i].nex) 31 if ((edge[i].len)&&(d[edge[i].to]<0)){ 32 d[edge[i].to]=d[k]+1; 33 q.push(edge[i].to); 34 } 35 } 36 return d[a[0].y]>=0; 37 } 38 int dfs(int k,int s){ 39 if (k==a[0].y)return s; 40 int p; 41 for(int &i=work[k];i!=-1;i=edge[i].nex) 42 if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){ 43 p=dfs(edge[i].to,min(s,edge[i].len)); 44 if (p){ 45 edge[i].len-=p; 46 edge[i^1].len+=p; 47 return p; 48 } 49 } 50 return 0; 51 } 52 int dinic(){ 53 int k,ans=0; 54 while (bfs()){ 55 memcpy(work,head,sizeof(head)); 56 while (k=dfs(a[0].x,inf))ans+=k; 57 } 58 return ans; 59 } 60 int main(){ 61 scanf("%d%d",&n,&m); 62 m++; 63 for(int i=1;i<=m;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); 64 a[0]=a[m]; 65 sort(a+1,a+m+1); 66 int ans=0; 67 for(int i=0;i<2;i++){ 68 memset(head,-1,sizeof(head)); 69 E=0; 70 for(int j=1;j<=m;j++) 71 if ((!i)&&(a[j]<a[0])||(i)&&(a[0]<a[j])){ 72 add(a[j].x,a[j].y,1); 73 add(a[j].y,a[j].x,1); 74 } 75 ans+=dinic(); 76 } 77 printf("%d",ans); 78 }