Codeforces 270E Flawed Flow 网络流问题
题意:给出一些边,给出边的容量。让你为所有边确定一个方向使得流量最大。
题目不用求最大流, 而是求每条边的流向,这题是考察网络流的基本规律。
若某图有最大,则有与源点相连的边必然都是流出的,与汇点相连的边必然是流入的,其它所有点流入和流出的流量是相等的。
我们可以根据这一规律来求解。
先求出所有点(除了源点和汇点)的总流量(表示流入的流量的2倍),每次流过该边,更新的时候减去流入流量的2倍。
从源点出发广搜每个点,搜的过程可以确定经过边的流向,当某个点的剩余总流量为0时,表示流入该点的流量边已经都处理完毕,将这点入栈。
特别注意:当 这个点是汇点时不要入栈, 不然会从汇点回流过来,不符合基本规律。
#include<bits/stdc++.h> using namespace std; const int MAXN = 200010; const int MAXM = MAXN * 2; struct Edge { int u,v,w; int next; int type,id; }edge[MAXM]; int head[MAXN],tot; void init() {tot = 0; memset(head,-1,sizeof(head));} void add_edge(int u,int v,int w,int type,int id) { edge[tot].u = u; edge[tot].v = v; edge[tot].w = w; edge[tot].type = type; edge[tot].id = id; edge[tot].next = head[u]; head[u] = tot++; } queue<int>q; int N,M; bool vis[MAXN]; int ans[MAXN],val[MAXN]; int main() { while (scanf("%d%d",&N,&M) != EOF) { init(); memset(val,0,sizeof(val)); for (int i = 0 ; i < M ; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add_edge(u,v,w,0,i + 1); add_edge(v,u,w,1,i + 1); val[u] += w; val[v] += w; } while (!q.empty()) q.pop(); vis[1] = true; q.push(1); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u] ; i != - 1 ; i = edge[i].next) { int v = edge[i].v; if (vis[v]) continue; val[v] -= 2 * edge[i].w; ans[edge[i].id] = edge[i].type; if (val[v] == 0 && v != N) { vis[v] = true; q.push(v); } } } for (int i = 1 ; i <= M ; i++) printf("%d\n",ans[i]); } return 0; }
今年输的,明年全都要赢回来