题目描述:
输入t,t个case。
输入n和m,n点,m边。
m行,from,to,l,r,4个整数,from到to,下界l,上界r。
没有可行流,输出no,否则,输入一种方案:原来每条边的距离流量是多少。
解题报告:
输入边的时候,对每个节点求出M[i],表示流入节点i的下界总和
减去
流出节点i的下界总和。
构图如下:
新建源点s,汇点t。
对于图中原来的边i,j,连接i,j,容量为r – l(上界减下界)
如果M[i] >=
0,连接s,i,容量M[i].
否则,连接i,t,容量-M[i]
求s到t的最大流。
如果源点或者汇点有一方满流,就存在可行解,否则不存在。
可行解为,当前边的流量加上这条边的下界。
讲解见周源的研究报告
代码如下:
//edge加了id和low变量,用于输出而已。
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstdio>
using
namespace std;
#define
Max 0x1fffffff
#define
SIZE 210
struct
edge{int from, to, val, next, id, low;}e[550000];
int
v[SIZE], que[SIZE], dis[SIZE], cnt, cur[SIZE], M[SIZE];
void
insert(int from, int to, int va, int id, int low)
{
e[cnt].from = from, e[cnt].to = to; e[cnt].val = va;
e[cnt].low = low;
e[cnt].next = v[from]; e[cnt].id = id; v[from] = cnt++;
e[cnt].from = to, e[cnt].to = from; e[cnt].val = 0;
e[cnt].next = v[to];v[to] = cnt++;
}
bool
bfs(int n, int s, int t)
{
int head, tail, id;
head = tail = 0; que[tail++] = s;
memset(dis, -1, sizeof(int) * n);dis[s] = 0;
while(head < tail) // bfs,得到顶点i的距s的最短距离dis[i]
for(id = v[que[head++]]; id != -1; id = e[id].next)
if (e[id].val > 0 &&
dis[e[id].to] == -1)
{
dis[e[id].to] = dis[e[id].from] + 1;
que[tail++] = e[id].to;
if (e[id].to == t) return true;
}
return false;
}
int
Dinic(int n, int s, int t)
{
int maxflow = 0, tmp, i;
while(bfs(n, s, t))
{
int u = s, tail = 0;
for(i = 0; i < n; i++) cur[i] = v[i];
while(cur[s] != -1)
if (u != t && cur[u] != -1
&& e[cur[u]].val > 0
&& dis[u] != -1
&& dis[u] + 1 ==
dis[e[cur[u]].to])
{que[tail++] = cur[u]; u = e[cur[u]].to;}
else if (u == t)
{
for(tmp = Max, i = tail - 1; i >= 0; i--) tmp =
min(tmp, e[que[i]].val);
for(maxflow += tmp, i = tail - 1; i >= 0;
i--)
{
e[que[i]].val -= tmp;
e[que[i] ^ 1].val += tmp;
if
(e[que[i]].val == 0) tail = i;
}
u = e[que[tail]].from;
}
else
{
while(tail > 0 && u
!= s && cur[u] == -1) u =
e[que[--tail]].from;
cur[u] = e[cur[u]].next;
}
}
return maxflow;
}
int n,
m;
bool
solve()
{
scanf("%d%d", &n, &m);
memset(M, 0, sizeof(M)); memset(v, -1, sizeof(v)); cnt =
0;
int s = 0, t = n + 1;
for(int i = 0; i < m; i++)
{
int from, to, l, r;
scanf("%d%d%d%d", &from, &to,
&l, &r);
insert(from, to, r - l, i, l);
M[to] += l; M[from] -= l;
}
for(int i = 1; i <= n; i++)
if (M[i] >= 0) insert(s, i, M[i], -1,
-1);
else insert(i, t, -M[i], -1, -1);
Dinic(t + 1, s, t);
bool flag1 = true, flag2 = true;
for(int i = v[s]; i != -1; i = e[i].next)
if (e[i].val != 0){flag1 = false; break;}
for(int i = v[t]; i != -1; i = e[i].next)
if (e[i^1].val != 0){flag2 = false; break;}
return flag1 || flag2;
}
int
ans[SIZE * SIZE];
int
main()
{
int t;scanf("%d", &t);
while(t--)
{
if (solve())
{
printf("YES\n");
for(int i = 0; i < cnt; i += 2) if (e[i].id
>= 0)
ans[e[i].id] = e[i^1].val + e[i].low;
for(int i = 0; i < m; i++)
printf("%d\n", ans[i]);
printf("\n");
}else printf("NO\n\n");
}
return 0;
}
加载中,请稍候......