网络流之最小割

最小割的相关知识请参见:网络流问题

I.     hdu4289    Control

题意:给出一个由n个点,m条边组成的无向图。给出两个点s,t。对于图中的每个点,去掉这个点都需要一定的花费。求至少多少花费才能使得s和t之间不连通。

分析:题意即求最小割,将每个点拆点,点与对应点的边权为去掉该点的花费,原图中所有边的边权赋为无穷大,跑一遍最大流即可。(最大流即最小割)

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 
  6 using namespace std;
  7 const int MAXN = 2010;
  8 const int MAXM = 1200012;
  9 const int INF = 0x3f3f3f3f;
 10 struct Edge 
 11 {
 12     int to, next, cap, flow;
 13 }edge[MAXM];
 14 int tol;
 15 int head[MAXN];
 16 void init() 
 17 {
 18     tol = 2;
 19     memset(head, -1, sizeof(head));
 20 }
 21 void addedge(int u, int v, int w, int rw=0) 
 22 {
 23     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
 24     edge[tol].next = head[u]; head[u] = tol++;
 25     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
 26     edge[tol].next = head[v]; head[v] = tol++;
 27 }
 28 int Q[MAXN];
 29 int dep[MAXN], cur[MAXN], sta[MAXN];
 30 bool bfs(int s, int t, int n) 
 31 {
 32     int front = 0, tail = 0;
 33     memset(dep, -1, sizeof(dep[0])*(n+1));
 34     dep[s] = 0;
 35     Q[tail++] = s;
 36     while(front < tail)
 37     {
 38         int u = Q[front++];
 39         for(int i = head[u]; i != -1; i = edge[i].next) 
 40         {
 41             int v = edge[i].to;
 42             if(edge[i].cap > edge[i].flow && dep[v] == -1)                 {
 43                 dep[v] = dep[u] + 1;
 44                 if(v == t) return true;
 45                 Q[tail++] = v;
 46             }
 47         }
 48     }
 49     return false;
 50 }
 51 int dinic(int s, int t, int n) {
 52     int maxflow = 0;
 53     while(bfs(s, t, n)) {
 54         for(int i = 0; i < n; i++) cur[i] = head[i];
 55         int u = s, tail = 0;
 56         while(cur[s] != -1)
 57         {
 58             if(u == t) 
 59             {
 60                 int tp = INF;
 61                 for(int i = tail-1; i >= 0; i--)
 62                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
 63                 maxflow+=tp;
 64                 for(int i = tail-1; i >= 0; i--) {
 65                     edge[sta[i]].flow+=tp;
 66                     edge[sta[i]^1].flow-=tp;
 67                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
 68                         tail = i;
 69                 }
 70                 u = edge[sta[tail]^1].to;
 71             }
 72             else 
 73                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
 74                 {
 75                     sta[tail++] = cur[u];
 76                     u = edge[cur[u]].to;
 77                 }
 78                 else 
 79                 {
 80                     while(u != s && cur[u] == -1)
 81                         u = edge[sta[--tail]^1].to;
 82                     cur[u] = edge[cur[u]].next;
 83                 }
 84         }
 85     }
 86     return maxflow;
 87 }
 88 int n,m,s,d;
 89 
 90 int main()
 91 {
 92     while(~scanf("%d%d",&n,&m))
 93     {
 94         init();
 95         scanf("%d%d",&s,&d);
 96         int c;
 97         for(int i=0;i<n;++i)
 98         {
 99             scanf("%d",&c);
100             addedge(i,i+n,c);
101         }
102         for(int i=1;i<=m;++i)
103         {
104             int a,b;
105             scanf("%d%d",&a,&b);
106             addedge(a-1+n,b-1,INF);
107             addedge(b-1+n,a-1,INF);
108         }
109         cout<<dinic(s-1,d-1+n,2*n)<<endl;
110     }
111     return 0;
112 }
View Code

 J.     UVA10480    Sabotage

题意:旧政府有一个很庞大的网络系统,可以很方便的指挥他的城市,起义军为了减少伤亡所以决定破坏他们的网络,使他们的首都(1号城市)和最大的城市(2号城市)不能联

系,不过破坏不同的网络所花费的代价是不同的,现在起义军想知道最少花费的代价是多少,输出需要破坏的线路。

分析:与 I 题一样,也是求最小割,只要算出最大流即可。不过题目要求输出最小割的边,这也是可以用网络流解决的,方法:求完最大流后,在残留网络中从源点 s 开始 dfs ,将能

到达的点标号( c - f >0 的边),最后遍历一遍边集,将起点被标记、终点未被标记的边输出。(注意这是无向图,边只用输出一遍,而在有向图中,条件应该改为起点标号、终点未标或起点未标、终点标号的边)。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 
  7 using namespace std;
  8 const int MAXN = 200;
  9 const int MAXM = 5000;
 10 const int INF = 0x3f3f3f3f;
 11 struct Edge 
 12 {
 13     int from,to, next, cap, flow;
 14 }edge[MAXM];
 15 int tol;
 16 int head[MAXN];
 17 void init() 
 18 {
 19     tol = 2;
 20     memset(head, -1, sizeof(head));
 21 }
 22 int min(int a,int b)
 23 {
 24     return a>b?b:a;
 25 }
 26 void addedge(int u, int v, int w, int rw=0) 
 27 {
 28     edge[tol].from=u;
 29     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
 30     edge[tol].next = head[u]; head[u] = tol++;
 31 }
 32 int Q[MAXN];
 33 int dep[MAXN], cur[MAXN], sta[MAXN];
 34 bool bfs(int s, int t, int n) 
 35 {
 36     int front = 0, tail = 0;
 37     memset(dep, -1, sizeof(dep[0])*(n+1));
 38     dep[s] = 0;
 39     Q[tail++] = s;
 40     while(front < tail)
 41     {
 42         int u = Q[front++];
 43         for(int i = head[u]; i != -1; i = edge[i].next) 
 44         {
 45             int v = edge[i].to;
 46             if(edge[i].cap > edge[i].flow && dep[v] == -1)                         {
 47                 dep[v] = dep[u] + 1;
 48                 if(v == t) return true;
 49                 Q[tail++] = v;
 50             }
 51         }
 52     }
 53     return false;
 54 }
 55 int dinic(int s, int t, int n) {
 56     int maxflow = 0;
 57     while(bfs(s, t, n)) {
 58         for(int i = 0; i < n; i++) cur[i] = head[i];
 59         int u = s, tail = 0;
 60         while(cur[s] != -1)
 61         {
 62             if(u == t) 
 63             {
 64                 int tp = INF;
 65                 for(int i = tail-1; i >= 0; i--)
 66                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
 67                 maxflow+=tp;
 68                 for(int i = tail-1; i >= 0; i--) {
 69                     edge[sta[i]].flow+=tp;
 70                     edge[sta[i]^1].flow-=tp;
 71                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
 72                         tail = i;
 73                 }
 74                 u = edge[sta[tail]].from;
 75             }
 76             else 
 77                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
 78                 {
 79                     sta[tail++] = cur[u];
 80                     u = edge[cur[u]].to;
 81                 }
 82                 else 
 83                 {
 84                     while(u != s && cur[u] == -1)
 85                         u = edge[sta[--tail]].from;
 86                     cur[u] = edge[cur[u]].next;
 87                 }
 88         }
 89     }
 90     return maxflow;
 91 }
 92 int n,m;
 93 bool vis[MAXN];
 94 
 95 void dfs(int u)
 96 {
 97     vis[u]=true;
 98     for(int i=head[u];i!=-1;i=edge[i].next)
 99     {
100         int v=edge[i].to;
101         if(edge[i].cap>edge[i].flow&&(!vis[v]))
102                 dfs(v);
103     }
104 }
105 
106 int main()
107 {
108     while(~scanf("%d%d",&n,&m)&&n&&m)
109     {
110         init();
111         for(int i=1;i<=m;++i)
112         {
113             int u,v,c;
114             scanf("%d%d%d",&u,&v,&c);
115             addedge(u-1,v-1,c);
116             addedge(v-1,u-1,c);
117         }
118         dinic(0,1,n);
119         memset(vis,false,sizeof(vis));
120         dfs(0);
121         for(int i=2;i<tol;i=i+2)
122         {
123             int u=edge[i].from;
124             int v=edge[i].to;
125             if(vis[u]!=vis[v])
126             {
127                 cout<<u+1<<" "<<v+1<<endl;
128             }
129         }
130         cout<<endl;
131     }
132     return 0;
133 }
View Code
原文地址:https://www.cnblogs.com/yaoyueduzhen/p/5080048.html