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;
}

 

posted @ 2016-03-31 23:38  Commence  阅读(482)  评论(0编辑  收藏  举报