UVa 10480:Sabotage (最小割集)

时间:2021-03-13 04:24:49

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1421

题意:给出n个点m条边,每条边有一个花费,问将1和2隔离需要破坏的边的最小花费的边集。

思路:很明显是最小割,但是问题在于如何求出这个最小割集。通过以前的题目,求网络的最大流就是求网络的最小割,那么从源点到汇点的最大流必定就会经过最小割集的边,当这条边满载(flow == cap)的时候,这条边其实就是最小割集的边。求出最大流之后,整个残余网络会被分成两个集合,一个和源点直接间接相连的点集,另一个和汇点直接间接相连的点集,所以只要BFS从源点或者汇点往前扫,一边扫一边标记,直到扫到(flow == cap)的边就停止。然后枚举边,如果一条边有一边的顶点是被标记过的,另一边的顶点没被标记,那么这条边就是最小割集之一了。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <string>
  7 #include <iostream>
  8 #include <stack>
  9 #include <map>
 10 #include <queue>
 11 #include <set>
 12 using namespace std;
 13 typedef long long LL;
 14 #define N 55
 15 #define M 505
 16 #define INF 0x3f3f3f3f
 17 struct Edge {
 18     int u, v, cap;
 19     Edge () {}
 20     Edge (int u, int v, int cap) : u(u), v(v), cap(cap) {}
 21 } edge[M*4];
 22 vector<int> G[N];
 23 int dis[N], cur[N], S, T, tot, vis[N], mp[N][N];
 24 
 25 void Add(int u, int v, int cap) {
 26     edge[tot] = Edge(u, v, cap);
 27     G[u].push_back(tot++);
 28     edge[tot] = Edge(v, u, 0);
 29     G[v].push_back(tot++);
 30 }
 31 
 32 int BFS() {
 33     memset(dis, INF, sizeof(dis));
 34     queue<int> que;
 35     que.push(S); dis[S] = 0;
 36     while(!que.empty()) {
 37         int u = que.front(); que.pop();
 38         for(int i = 0; i < G[u].size(); i++) {
 39             Edge &e = edge[G[u][i]];
 40             if(dis[e.v] == INF && e.cap > 0) {
 41                 dis[e.v] = dis[u] + 1;
 42                 que.push(e.v);
 43             }
 44         }
 45     }
 46     return dis[T] < INF;
 47 }
 48 
 49 int DFS(int u, int maxflow) {
 50     if(u == T) return maxflow;
 51     for(int i = cur[u]; i < G[u].size(); i++) {
 52         cur[u] = i;
 53         Edge &e = edge[G[u][i]];
 54         if(dis[e.v] == dis[u] + 1 && e.cap > 0) {
 55             int flow = DFS(e.v, min(e.cap, maxflow));
 56             if(flow > 0) {
 57                 e.cap -= flow;
 58                 edge[G[u][i]^1].cap += flow;
 59                 return flow;
 60             }
 61         }
 62     }
 63     return 0;
 64 }
 65 
 66 int Dinic() {
 67     int ans = 0;
 68     while(BFS()) {
 69         int flow;
 70         memset(cur, 0, sizeof(cur));
 71         while(flow = DFS(S, INF)) ans += flow;
 72     }
 73     return ans;
 74 }
 75 
 76 void bfs() {
 77     queue<int> que;
 78     que.push(S); vis[S] = 1;
 79     while(!que.empty()) {
 80         int u = que.front(); que.pop();
 81         for(int i = 0; i < G[u].size(); i++) {
 82             Edge &e = edge[G[u][i]];
 83             if(!vis[e.v] && e.cap > 0) {
 84                 vis[e.v] = 1;
 85                 que.push(e.v);
 86             }
 87         }
 88     }
 89 }
 90 
 91 int main()
 92 {
 93     int n, m;
 94     while(~scanf("%d%d", &n, &m), n + m) {
 95         int u, v, cap; tot = 0;
 96         for(int i = 1; i <= n; i++) G[i].clear();
 97         memset(mp, 0, sizeof(mp));
 98         memset(vis, 0, sizeof(vis));
 99         for(int i = 0; i < m; i++) {
100             scanf("%d%d%d", &u, &v, &cap);
101             Add(u, v, cap); Add(v, u, cap);
102         } S = 1, T = 2;
103         Dinic();
104         bfs();
105         for(int u = 1; u <= n; u++) {
106             for(int i = 0; i < G[u].size(); i++) {
107                 int v = edge[G[u][i]].v;
108                 if(vis[u] && !vis[v] || vis[v] && !vis[u]) mp[u][v] = mp[v][u] = 1;
109             }
110         }
111         for(int i = 1; i <= n; i++) {
112             for(int j = i + 1; j <= n; j++) {
113                 if(mp[i][j]) printf("%d %d\n", i, j);
114             }
115         }
116         puts("");
117     }
118     return 0;
119 }