最大流最小割 UVA
阿新 • • 發佈:2018-12-30
題意:輸入一個n和m,n為點數,m為邊數,接下來m行u, v, w,求1和2不連線的最小花費。
解題:最大流最小割定理,要輸出割斷的邊。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; struct node { int from, to, cap, next; } edge[2000000]; int dep[100000], head[100000], vist[1000000]; int src, des, cnt, n, m; const int INF = 1e9; void addedge(int u, int v, int w) { edge[cnt].from = u, edge[cnt].to = v, edge[cnt].cap = w, edge[cnt].next = head[u]; head[u] = cnt++; edge[cnt].from = v, edge[cnt].to = u, edge[cnt].cap = w, edge[cnt].next = head[v]; head[v] = cnt++; return ; } int bfs() { queue<int>que; memset(dep, -1, sizeof(dep)); dep[src] = 0; que.push(src); while(!que.empty()) { int u = que.front(); que.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { // printf("**********\n"); int v = edge[i].to; if(dep[v]==-1 && edge[i].cap > 0) { dep[v] = dep[u]+1; que.push(v); } } } return dep[des]!=-1; } int dfs(int u, int minc) { if(u == des) return minc; int tmp; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(dep[v]==dep[u]+1 && edge[i].cap>0 && (tmp=dfs(v, min(minc, edge[i].cap))) ) { edge[i].cap -= tmp; edge[i^1].cap += tmp; return tmp; } } dep[u] = -1; return 0; } int dinic() { int ans = 0, tmp; while(bfs()) { while(tmp=dfs(src, INF)) ans += tmp; } return ans; } void bbfs(int s, int c) // 記錄點集 { queue<int> que; que.push(s); vist[s] = c; while(!que.empty()) { int u = que.front(); que.pop(); for(int i = head[u]; i!=-1; i = edge[i].next) { int v = edge[i].to; if(edge[i].cap > 0 && !vist[v]) { vist[v] = c; que.push(v); } } } return ; } int main() { int u, v, w; while(~scanf("%d%d", &n, &m) && (n+m)) { src = 1, des = 2; cnt = 0; memset(head, -1, sizeof(head)); while(m--) { scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); } dinic(); memset(vist, 0, sizeof(vist)); bbfs(src, 1); bbfs(des, 2); for(int i = 0; i < cnt; i++) { if(edge[i].cap==0 && vist[edge[i].from]!=vist[edge[i].to]) printf("%d %d\n", edge[i].from, edge[i].to); } printf("\n"); } return 0; }