ZOJ2314 Reactor Cooling

来源:互联网 发布:安能快递有淘宝店用吗 编辑:程序博客网 时间:2024/06/05 17:41

一.题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314

二,题目大意:给一个无汇源点,流量有上下界限的图,求出是否有可行流,如果有,输出每条管子上的最大流。

三.思路:首先判断有无可行流,由于流量有上下界,于是,自然而然想到了每条弧用上界减去下界,但是这样违反了流量守恒(流入一个节点的流等于流出的)。

比如说:(u,v)上下界为(1,3), (v, q)上下界为(3,4)一条边减去2,另一条边减去了1,减去的流量不相等,相当于1的流量积累在v。于是我们可以想到建立源点、汇点来导流。

具体建图如下:

1.记录每个点的D = (每条进入它的弧的下界) 减去 (由它出发的弧的下界)。如果大于0,得到的就是积累在本节点的流量,于是建立一个汇点,把流导给它。容量为D。如果小于0,得到的就是本节点所需要进入的流量,建立一个源点s,跟它相连,容量为-D。

2.当然原来容量网络的每条弧保持一样,容量变为上界 减去 下界。

        对于构造出来的图我们叫它伴随网络,(当然它的每条弧下界都为0)只有伴随网络的最大流使得从源点S出发,每条弧都满了(此时连到T的弧也一定会满),原来网络才有可行流。而本题还要求原容量网络中每条弧的可行流的流量,其实它只等于伴随网络中所对应的弧的流量加上每条弧流量的下界。而对于邻接表建图的话,伴随网络中所对应的弧的流量,就是第2*i条边的反向弧最后的流量。也就是2*i^1。

四.代码:

#include <iostream>#include <cstdio>#include <queue>#include <cstring>#include <cstdlib>using namespace std;const int INF = 0x3f3f3f3f,          MAX_N = 209;class Dinic{public:    struct Edge    {        int v, w, next;    };    int cnt, head[MAX_N], dist[MAX_N], s, t;    Edge edges[MAX_N*MAX_N];    void init(int is, int it)    {        cnt = 0;        s = is, t = it;        memset(head, -1, sizeof(head));    }    void addEdge(int u, int v, int weight)    {        edges[cnt] = (Edge){v, weight, head[u]};        head[u] = cnt++;        edges[cnt] = (Edge){u, 0, head[v]};        head[v] = cnt++;    }    bool BFS()    {        int i, cur;        queue <int> que;        que.push(s);        memset(dist, -1, sizeof(dist));        dist[s] = 0;        while(!que.empty()){            cur = que.front();            que.pop();            for(i = head[cur]; i != -1; i = edges[i].next)                if(-1 == dist[edges[i].v] && edges[i].w){                    dist[edges[i].v] = dist[cur] + 1;                    que.push(edges[i].v);                }        }        return dist[t] != -1;    }    int DFS(int start, int curFlow)    {        if(start == t)            return curFlow;        int i, minFlow = 0, v, temp;        for(i = head[start]; i != -1; i = edges[i].next){            v = edges[i].v;            if(dist[start] == dist[v] - 1 && edges[i].w > 0){                temp = DFS(v, min(edges[i].w, curFlow));                edges[i].w -= temp;                edges[i^1].w += temp;                curFlow -= temp;                minFlow += temp;                if(0 == curFlow)                    break;            }        }        if(0 == minFlow)            dist[start] = -2;        return minFlow;    }    int maxFlow()    {        int res = 0;        while(BFS()){            res += DFS(s, INF);        }        return res;    }}G;int nodeNum, edgeNum,    cnt[MAX_N];int main(){    //freopen("in.txt", "r", stdin);    int sum, i, j, test, u, v, down[MAX_N*MAX_N], up, s, t;    scanf("%d", &test);    while(test--){        scanf("%d%d", &nodeNum, &edgeNum);        s = nodeNum + 1, t = nodeNum + 2;        G.init(s, t);        memset(cnt, 0, sizeof(cnt));        for(i = 0; i < edgeNum; i++){            scanf("%d%d%d%d", &u, &v, &down[i], &up);            cnt[u] += down[i], cnt[v] -= down[i];            G.addEdge(u, v, up - down[i]);        }        sum = 0;        for(i = 1; i <= nodeNum; i++){            if(cnt[i] > 0){                G.addEdge(i, t, cnt[i]);                sum += cnt[i];            }            else if(cnt[i] < 0)                G.addEdge(s, i, -cnt[i]);        }        if(sum == G.maxFlow()){            printf("YES\n");            for(i = 0; i < edgeNum; i++)                printf("%d\n", down[i] + G.edges[(2*i)^1].w);            printf("\n");        }        else            printf("NO\n\n");    }    return 0;}


0 0
原创粉丝点击