题目链接:https://vjudge.net/problem/UVA-10480
题解:
实际就是求最小割集。
1.什么是网络流图的“割”?答:一个边的集合,使得网络流图删除这些边之后,点被分成两部分S和T, 且源点位于S中, 汇点位于T中。注意:不能存在独立于S和T的点。
2.对于最小割集中的边,它在残余网络中容量为0。
3.从源点出发,沿着有残余容量的边走,能够访问到的点都属于S集合,否则属于T集合。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int mod = 1e9+7; 17 const int MAXN = 1e2+10; 18 19 int maze[MAXN][MAXN]; 20 int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN]; 21 int flow[MAXN][MAXN]; 22 23 int sap(int start, int end, int nodenum) 24 { 25 memset(cur, 0, sizeof(cur)); 26 memset(dis, 0, sizeof(dis)); 27 memset(gap, 0, sizeof(gap)); 28 memset(flow, 0, sizeof(flow)); 29 int u = pre[start] = start, maxflow = 0, aug = INF; 30 gap[0] = nodenum; 31 32 while(dis[start]<nodenum) 33 { 34 loop: 35 for(int v = cur[u]; v<nodenum; v++) 36 if(maze[u][v]-flow[u][v]>0 && dis[u] == dis[v]+1) 37 { 38 aug = min(aug, maze[u][v]-flow[u][v]); 39 pre[v] = u; 40 u = cur[u] = v; 41 if(v==end) 42 { 43 maxflow += aug; 44 for(u = pre[u]; v!=start; v = u, u = pre[u]) 45 { 46 flow[u][v] += aug; 47 flow[v][u] -= aug; 48 } 49 aug = INF; 50 } 51 goto loop; 52 } 53 54 int mindis = nodenum-1; 55 for(int v = 0; v<nodenum; v++) 56 if(maze[u][v]-flow[u][v]>0 && mindis>dis[v]) 57 { 58 cur[u] = v; 59 mindis = dis[v]; 60 } 61 if((--gap[dis[u]])==0) break; 62 gap[dis[u]=mindis+1]++; 63 u = pre[u]; 64 } 65 return maxflow; 66 } 67 68 bool vis[MAXN]; 69 void dfs(int u, int n) 70 { 71 vis[u] = true; 72 for(int v = 0; v<n; v++) 73 if(maze[u][v]-flow[u][v] && !vis[v]) 74 dfs(v, n); 75 } 76 77 int edge[MAXN*MAXN][2]; 78 int main() 79 { 80 int n, m; 81 while(scanf("%d%d", &n, &m)&&(n||m)) 82 { 83 memset(maze, 0, sizeof(maze)); 84 for(int i = 1; i<=m; i++) 85 { 86 int u, v, w; 87 scanf("%d%d%d", &u,&v,&w); 88 edge[i][0] = --u; edge[i][1] = --v; 89 maze[u][v] = w; 90 maze[v][u] = w; 91 } 92 93 int start = 0, end = 1; 94 sap(start, end, n); 95 96 memset(vis, false, sizeof(vis)); 97 dfs(0, n); 98 for(int i = 1; i<=m; i++) 99 { 100 int u = edge[i][0]; 101 int v = edge[i][1]; 102 if( (vis[u] && !vis[v]) || (!vis[u] && vis[v]) ) 103 printf("%d %d ", u+1, v+1); 104 } 105 printf(" "); 106 } 107 }