ZJU-Reactor Cooling(无源汇有上下界最大流)

 题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2314

Reactor Cooling

Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge

The terrorist group leaded by a well known international terrorist Ben Bladen is buliding a nuclear reactor to produce plutonium for the nuclear bomb they are planning to create. Being the wicked computer genius of this group, you are responsible for developing the cooling system for the reactor.

The cooling system of the reactor consists of the number of pipes that special cooling liquid flows by. Pipes are connected at special points, called nodes, each pipe has the starting node and the end point. The liquid must flow by the pipe from its start point to its end point and not in the opposite direction.

Let the nodes be numbered from 1 to N. The cooling system must be designed so that the liquid is circulating by the pipes and the amount of the liquid coming to each node (in the unit of time) is equal to the amount of liquid leaving the node. That is, if we designate the amount of liquid going by the pipe from i-th node to j-th as fij, (put fij = 0 if there is no pipe from node i to node j), for each i the following condition must hold:

fi,1+fi,2+...+fi,N = f1,i+f2,i+...+fN,i

Each pipe has some finite capacity, therefore for each i and j connected by the pipe must be fij <= cij where cij is the capacity of the pipe. To provide sufficient cooling, the amount of the liquid flowing by the pipe going from i-th to j-th nodes must be at least lij, thus it must be fij >= lij.

Given cij and lij for all pipes, find the amount fij, satisfying the conditions specified above.

This problem contains multiple test cases!

The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.

The output format consists of N output blocks. There is a blank line between output blocks.

Input

The first line of the input file contains the number N (1 <= N <= 200) - the number of nodes and and M - the number of pipes. The following M lines contain four integer number each - i, j, lij and cij each. There is at most one pipe connecting any two nodes and 0 <= lij <= cij <= 10^5 for all pipes. No pipe connects a node to itself. If there is a pipe from i-th node to j-th, there is no pipe from j-th node to i-th.

Output

On the first line of the output file print YES if there is the way to carry out reactor cooling and NO if there is none. In the first case M integers must follow, k-th number being the amount of liquid flowing by the k-th pipe. Pipes are numbered as they are given in the input file.

Sample Input

2

4 6
1 2 1 2
2 3 1 2
3 4 1 2
4 1 1 2
1 3 1 2
4 2 1 2

4 6
1 2 1 3
2 3 1 3
3 4 1 3
4 1 1 3
1 3 1 3
4 2 1 3

Sample Input

NO

YES
1
2
3
2
1
1

解题思路:设d[u]为顶点u入边下界和-出边下界和,新建源点、汇点,原网络的弧<u,v>容量设置成其上界-下界,对于每一个顶点u,如果d[u]>0则源点向其连容量d[u]的边,否则其向汇点连容量-d[u]的边,最后如果和源点相关的弧都满流则存在可行流,而各条边的流量+其在原网络的下界就是一个解。——https://www.cnblogs.com/WABoss/p/5371871.html

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned long long ull;
  5 #define INF 0x3f3f3f3f
  6 const ll MAXN = 200 + 7;
  7 const ll MAXM = 1e5 + 7;
  8 const ll MOD = 1e9 + 7;
  9 const double pi = acos(-1);
 10 int cnt = -1, head[MAXM], dis[MAXN], cur[MAXM];
 11 int n, m;
 12 struct edge
 13 {
 14     int to, value, net, num;
 15 } e[MAXM << 1]; ///共有n*2条边
 16 void add(int from, int to, int value, int num)
 17 { ///链式前向星
 18     cnt++;
 19     e[cnt].to = to;
 20     e[cnt].num = num;
 21     e[cnt].value = value;
 22     e[cnt].net = head[from];
 23     head[from] = cnt;
 24 }
 25 int bfs(int st, int ed)
 26 { ///建立层次图
 27     queue<int> que;
 28     memset(dis, -1, sizeof(dis));
 29     dis[st] = 0;
 30     que.push(st);
 31     while (!que.empty())
 32     {
 33         int x = que.front();
 34         que.pop();
 35         for (int i = head[x]; i > -1; i = e[i].net)
 36         {
 37             int now = e[i].to;
 38             if (dis[now] == -1 && e[i].value)
 39             {
 40                 que.push(now);
 41                 dis[now] = dis[x] + 1;
 42             }
 43         }
 44     }
 45     return dis[ed] != -1;
 46 }
 47 int dfs(int x, int t, int maxflow)
 48 {
 49     if (x == t)
 50         return maxflow;
 51     int ans = 0;
 52     for (int i = cur[x]; i > -1; i = e[i].net)
 53     { ///当前弧优化
 54         int now = e[i].to;
 55         if (dis[now] != dis[x] + 1 || e[i].value == 0 || ans >= maxflow)
 56             continue;
 57         cur[x] = i;
 58         int f = dfs(now, t, min(e[i].value, maxflow - ans));
 59         e[i].value -= f;
 60         e[i ^ 1].value += f; ///反向边加流量
 61         ans += f;
 62     }
 63     if (!ans)
 64         dis[x] = -1; ///炸点优化
 65     return ans;
 66 }
 67 int Dinic(int st, int ed)
 68 {
 69     int ans = 0;
 70     while (bfs(st, ed))
 71     {
 72         memcpy(cur, head, sizeof(head));
 73         int k;
 74         while ((k = dfs(st, ed, INF)))
 75             ans += k;
 76     }
 77     return ans;
 78 }
 79 int lowf[MAXM], totflow[MAXN];
 80 int ans[MAXM];
 81 void init()
 82 {
 83     cnt = -1;
 84     memset(head, -1, sizeof(head));
 85     memset(totflow, 0, sizeof(totflow));
 86 }
 87 int main()
 88 {
 89     int t;
 90     scanf("%d", &t);
 91     while (t--)
 92     {
 93         init();
 94         scanf("%d%d", &n, &m);
 95         for (int i = 1; i <= m; i++)
 96         {
 97             int from, to, v;
 98             scanf("%d%d%d%d", &from, &to, &lowf[i], &v);
 99             add(from, to, v - lowf[i], i);
100             add(to, from, 0, i);      //建图 令每条边的流量等于流量下限后的残量网络
101             totflow[from] -= lowf[i]; //流出
102             totflow[to] += lowf[i];   //流入
103             //流量守恒定律:每个点的总流入量=总流出量
104         }
105         int sumflow = 0;
106         for (int i = 1; i <= n; i++)
107         {
108             if (totflow[i] > 0)
109             {
110                 add(0, i, totflow[i], 0);
111                 add(i, 0, 0, 0);
112                 sumflow += totflow[i];
113             }
114             else
115             {
116                 add(i, n + 1, -totflow[i], 0);
117                 add(n + 1, i, 0, 0);
118             }
119         }
120         if (Dinic(0, n + 1) == sumflow) //总入流=总流量 则可行
121         {
122             printf("YES
");
123             for (int i = 1; i <= n; i++)
124             {
125                 for (int j = head[i]; j > -1; j = e[j].net)
126                 {
127                     if (e[j].num == 0 || j % 2 == 0)
128                         continue;
129                     else
130                         ans[e[j].num] = e[j].value + lowf[e[j].num];
131                 }
132             }
133             for (int i = 1; i <= m; i++)
134                 printf("%d
", ans[i]);
135         }
136         else
137             printf("NO
");
138         if (t)
139             printf("
");
140     }
141     return 0;
142 }
原文地址:https://www.cnblogs.com/graytido/p/10872577.html