题目链接:https://cn.vjudge.net/problem/UVA-10480
知识点: 最小割
题目大意:
求最小割并打印出最小割必须割掉的边。
解题思路:
在跑完 (sap) 后的残量网络上,记录源点和汇点可达的点,然后遍历所有的边(设边的两端点为 (u) 和 (v)),如果 (u) 源点可达而 (v) 汇点可达(或与之相反,(v) 源点可达而 (u) 汇点可达),则说明该边必须割。
AC代码:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int MAXN=52; 5 const int MAXM=1010; 6 const int INF=0x3f3f3f3f; 7 struct Edge{ 8 int from,to,Next,cap,flow; 9 }edge[MAXM]; 10 int flag[MAXN]; 11 int tol; 12 int head[MAXN]; 13 int gap[MAXN],dep[MAXN],cur[MAXN]; 14 void init(){ 15 tol=0; 16 memset(flag,0,sizeof(flag)); 17 memset(head,-1,sizeof(head)); 18 } 19 void addedge(int u,int v,int w,int rw){ 20 edge[tol].from=u; edge[tol].to=v; edge[tol].cap=w; edge[tol].flow=0; 21 edge[tol].Next=head[u]; head[u]=tol++; 22 edge[tol].from=v; edge[tol].to=u; edge[tol].cap=rw; edge[tol].flow=0; 23 edge[tol].Next=head[v]; head[v]=tol++; 24 } 25 int Q[MAXN]; 26 void BFS(int start,int ends){ 27 memset(dep,-1,sizeof(dep)); 28 memset(gap,0,sizeof(gap)); 29 gap[0]=1; 30 int fronts=0,rear=0; 31 dep[ends]=0; 32 Q[rear++]=ends; 33 while(fronts!=rear){ 34 int u=Q[fronts++]; 35 for(int i=head[u];i!=-1;i=edge[i].Next){ 36 int v=edge[i].to; 37 if(dep[v]!=-1) continue; 38 Q[rear++]=v; 39 dep[v]=dep[u]+1; 40 gap[dep[v]]++; 41 } 42 } 43 } 44 int S[MAXN]; 45 int sap(int start,int ends,int N){ 46 BFS(start,ends); 47 memcpy(cur,head,sizeof(head)); 48 int top=0; 49 int u=start; 50 int ans=0; 51 while(dep[start]<N){ 52 if(u==ends){ 53 int Min=INF; 54 int inser; 55 for(int i=0;i<top;i++){ 56 if(Min>edge[S[i]].cap-edge[S[i]].flow){ 57 Min=edge[S[i]].cap-edge[S[i]].flow; 58 inser=i; 59 } 60 } 61 for(int i=0;i<top;i++){ 62 edge[S[i]].flow+=Min; 63 edge[S[i]^1].flow-=Min; 64 } 65 ans+=Min; 66 top=inser; 67 u=edge[S[top]^1].to; 68 continue; 69 } 70 bool flag=false; 71 int v; 72 for(int i=cur[u];i!=-1;i=edge[i].Next){ 73 v=edge[i].to; 74 if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]){ 75 flag=true; 76 cur[u]=i; 77 break; 78 } 79 } 80 if(flag){ 81 S[top++]=cur[u]; 82 u=v; 83 continue; 84 } 85 int Min=N; 86 for(int i=head[u];i!=-1;i=edge[i].Next){ 87 if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min){ 88 Min=dep[edge[i].to]; 89 cur[u]=i; 90 } 91 } 92 gap[dep[u]]--; 93 if(!gap[dep[u]]) return ans; 94 dep[u]=Min+1; 95 gap[dep[u]]++; 96 if(u!=start) u=edge[S[--top]^1].to; 97 } 98 return ans; 99 } 100 void dfs(int x,int od){ 101 flag[x]=od; 102 for(int i=head[x];i!=-1;i=edge[i].Next){ 103 if(edge[i].flow==edge[i].cap) continue; 104 if(!flag[edge[i].to]) 105 dfs(edge[i].to,od); 106 } 107 } 108 int main(){ 109 // freopen("in.txt","r",stdin); 110 // freopen("out.txt","w",stdout); 111 int n,m; 112 while(scanf("%d%d",&n,&m)==2&&n){ 113 init(); 114 int u,v,w; 115 for(int i=0;i<m;i++){ 116 scanf("%d%d%d",&u,&v,&w); 117 addedge(u,v,w,w); 118 } 119 sap(1,2,n); 120 dfs(1,1); 121 dfs(2,2); 122 for(int i=0;i<tol;i+=2){ 123 int u=edge[i].from,v=edge[i].to; 124 if((flag[u]==1&&flag[v]==2)||(flag[u]==2&&flag[v]==1)) 125 printf("%d %d ",u,v); 126 } 127 printf(" "); 128 } 129 return 0; 130 }