UVA10480 Sabotage

题目链接: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 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
原文地址:https://www.cnblogs.com/Blogggggg/p/9250326.html