对于无源汇问题,方法有两种.
1 从边的角度来处理. 新建超级源汇, 对于每一条有下界的边,x->y, 建立有向边 超级源->y ,容量为x->y下界,建立有向边 x-> 超级汇,容量为x->y下界.建立有向边 x->y,容量为x->y的上界减下界.
2 从点的角度来处理. 新建超级源汇,对于每个点流进的下界和为 in, 流出此点的下界和为out.如果in > out. 建立有向边 超级源->i,容量为in-out.反之,建立有向边 i->超级汇,容量为out-in.
如果超级源的每一条出边都满流,则存在一个可行流,可行流的流量就是每一条逆向边的流量+ 此边下界.
从点的角度的处理方法是边的处理方法的拓展.基于边的处理比较容易理解,但是复杂度较高.
下面是基于点的处理的程序:
1: /*
2: 带上下界的可行流
3: */
4: #include<iostream>
5: #include<cmath>
6: #include<memory>
7: #include <string.h>
8: #include <cstdio>
9: using namespace std;
10:
11: #define V 300 // vertex
12: #define E 40800 // edge
13: #define INF 0x3F3F3F3F // 1061109567
14:
15: int i,j,k;
16: #define REP(i,n) for((i)=0;(i)<(int)(n);(i)++)
17: #define snuke(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
18:
19: struct MaxFlow
20: {
21: struct Edge
22: {
23: int v, w, next; //w for capicity
24: int lb,up;
25: } edge[E];
26:
27: int head[V]; // head[u]表示顶点u第一条邻接边的序号, 若head[u] = -1, u没有邻接边
28: int e; // the index of the edge
29: int src, sink;
30: int net[V]; // 流入此节点的流的下界和 - 流出此节点的流的下界和,对于带上下界的来进行使用
31:
32:
33: void addedge(int u, int v, int w, int lb = 0, int up = INF, int rw = 0)
34: {
35: edge[e].v = v;
36: edge[e].w= w;
37: edge[e].next = head[u];
38: edge[e].lb = lb, edge[e].up = up;
39: head[u] = e++;
40: // reverse edge v -> u
41: edge[e].v = u;
42: edge[e].w = rw;
43: edge[e].lb = lb, edge[e].up = up;
44: edge[e].next = head[v];
45: head[v] = e++;
46: }
47:
48: int ISAP(int VertexNum )
49: {
50: int u, v, max_flow, aug, min_lev;
51: int curedge[V], parent[V], level[V];
52: int count[V], augment[V];
53:
54: memset(level, 0, sizeof(level));
55: memset(count, 0, sizeof(count));
56: REP(i,VertexNum+1) curedge[i] = head[i];
57: max_flow = 0;
58: augment[src] = INF;
59: parent[src] = -1;
60: u = src;
61:
62: while (level[src] < VertexNum)
63: {
64: if (u == sink)
65: {
66: max_flow += augment[sink];
67: aug = augment[sink];
68: for (v = parent[sink]; v != -1; v = parent[v])
69: {
70: i = curedge[v];
71: edge[i].w -= aug;
72: edge[i^1].w += aug;
73: augment[edge[i].v] -= aug;
74: if (edge[i].w == 0) u = v;
75: }
76: }
77: for (i = curedge[u]; i != -1; i = edge[i].next)
78: {
79: v = edge[i].v;
80: if (edge[i].w > 0 && level[u] == (level[v]+1))
81: {
82: augment[v] = min(augment[u], edge[i].w);
83: curedge[u] = i;
84: parent[v] = u;
85: u = v;
86: break;
87: }
88: }
89: if (i == -1)
90: {
91: if (--count[level[u]] == 0) break;
92: curedge[u] = head[u];
93: min_lev = VertexNum;
94: for (i = head[u]; i != -1; i = edge[i].next)
95: if (edge[i].w > 0)
96: min_lev = min(level[edge[i].v], min_lev);
97: level[u] = min_lev + 1;
98: count[level[u]]++;
99: if (u != src ) u = parent[u];
100: }
101: }
102: return max_flow;
103: }
104: void solve()
105: {
106: int T; cin>>T;
107: for(int cas =1; cas <=T; cas++)
108: {
109: int N,M; cin>>N>>M;
110: e = 0;
111: memset(head, -1, sizeof(head));
112: memset(net, 0, sizeof(net));
113: int a,b,c,d;
114: for(int i=1; i<=M;i++)
115: {
116: scanf("%d%d%d%d", &a, &b, &c, &d);
117: net[b] += c; net[a] -= c;
118: addedge(a,b,d-c, c,d);
119: }
120: // 无源汇,这两个是super src, super sink.
121: src =N+1; sink = N+2;
122: for(int i=1; i<=N; i++)
123: {
124: if(net[i] > 0)
125: addedge(src, i, net[i]);
126: else
127: addedge(i, sink, -net[i]);
128: }
129: ISAP(N+2);
130: bool flag = true;
131: for (i = head[src]; i != -1; i = edge[i].next)
132: {
133: if(edge[i].w !=0)
134: {
135: flag = false;
136: break;
137: }
138: }
139: if(flag)
140: {
141: cout<<"YES"<<endl;
142: for(int i=0; i<M;i++)
143: {
144: cout<<edge[i*2+1].w + edge[i*2+1].lb<<endl;
145: }
146: cout<<endl;
147: }else
148: {
149: cout<<"NO"<<endl;
150: cout<<endl;
151: }
152: }
153:
154: }
155: }sap;
156:
157: int main()
158: {
159: // freopen("1.txt","r",stdin);
160: sap.solve();
161: return 0;
162: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
ZOJ 2314 带上下界的可行流的更多相关文章
-
HDU Destroy Transportation system(有上下界的可行流)
前几天正看着网络流,也正研究着一个有上下界的网络流的问题,查看了很多博客,觉得下面这篇概括的还是相当精确的: http://blog.csdn.net/leolin_/article/details/ ...
-
[ACdream 1211 Reactor Cooling]无源无汇有上下界的可行流
题意:无源无汇有上下界的可行流 模型 思路:首先将所有边的容量设为上界减去下界,然后对一个点i,设i的所有入边的下界和为to[i],所有出边的下界和为from[i],令它们的差为dif[i]=to[i ...
-
ZOJ 2314 有上下界的网络流
problemCode=2314">点击打开链接 题意:给定m条边和n个节点.每条边最少的流量和最多的流量.保证每一个节点的出入流量和相等,问能够形成吗,能够则输出每条边的流量 思路: ...
-
BZOJ2406矩阵——有上下界的可行流+二分答案
题目描述 输入 第一行两个数n.m,表示矩阵的大小. 接下来n行,每行m列,描述矩阵A. 最后一行两个数L,R. 输出 第一行,输出最小的答案: 样例输入 2 2 0 1 2 1 0 1 样例输出 1 ...
-
【BZOJ2406】矩阵 二分+有上下界的可行流
[BZOJ2406]矩阵 Description Input 第一行两个数n.m,表示矩阵的大小. 接下来n行,每行m列,描述矩阵A. 最后一行两个数L,R. Output 第一行,输出最小的答案: ...
-
SGU 194 Reactor Cooling Dinic求解 无源无汇有上下界的可行流
题目链接 题意:有向图中有n(1 <= n <= 200)个点,无自环或者环的节点个数至少为3.给定每条边的最小流量和最大流量,问每条边的可行流量为多少? 思路:一般求解的网络流并不考虑下 ...
-
ZOJ 2314 Reactor Cooling | 无源汇可行流
题目: 无源汇可行流例题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 题解: 证明什么的就算了,下面给出一种建图方式 ...
-
bzoj 2406 二分+有源有汇上下界网络流可行流判定
弱爆了,典型的行列建模方式,居然想不到,题做少了,总结少了...... 二分答案mid s----------------------->i行-----------------------> ...
-
sgu 194 上下界网络流可行流判定+输出可行流
#include <cstdio> #include <cstring> #define min(a,b) ((a)<(b)?(a):(b)) #define oo 0x ...
随机推荐
-
Linux 自动同步服务器时间
200 ? "200px" : this.width)!important;} --> 介绍 Linux服务器运行久时,系统时间就会存在一定的误差,本篇文章就来介绍怎样使服务 ...
-
phpDocumentor 注释语法详解
PHPDocumentor是强大的代码注释生成器,本文对各个参数进行了简单地的总结: @abstract-------------使用@abstract标记来声明一个方法,类变量或类必须重新定义子类中 ...
-
php和java的memcached使用的兼容性问题解决过程
1. 背景: php 使用memcached客户端设置一个key,java使用java-memcached-client去读,报错如下: ERROR|com.whalin.MemCached.MemC ...
-
对象的类型转换P109
类作为一种应用数据类型,和基本数据类型的变量一样.不同类中存在对象与对象之间的类型转问题,对象的类型转换只能在 具有继承关系的 父类对象-----子类对象 之间进行 子类通常比父类拥有更多的域和 ...
-
RMAN-06023: no backup or copy of datafile 6 found to restore
一:问题描述 我用指定备份集恢复时,报错: RMAN> run { 2> shutdown immediate; 3> startup mount; 4> allocate c ...
-
HDU 2178 猜数字
题解:设猜到的最大的数是h,在1到h间,你最多只要猜log2(h)+1(取整)次,所以易知==>h=2^m-1.即猜m次,能猜到的最大的数为2^m-1. #include <cstdio& ...
-
mysql与oracle在groupby语句上的细节差异
前言 之所以去纠那么细节的问题,是因为之前有过一个这样的场景: 有个同学,给了一条数据库的语句给我,问,为啥这样子的语句在oracle语句下执行不了. select * from xx where x ...
-
X509证书认证流程介绍
X509证书介绍X.509 是由国际电信联盟(ITU-T)制定的数字证书标准,相信这是人尽皆知的了,目前X.509证书据我所知有三个版本,.net中使用的是x.509-2,X.509-2 版引入了主体 ...
-
子域名枚举工具Sublist3r
子域名枚举工具Sublist3r 通过搜集子域名信息,可以找到目标的关联网站,找寻相应的漏洞.Kali Linux提供一款基于OSINT的枚举工具Sublist3r.该工具会搜索多个数据来源,如G ...
-
深入学习c++--智能指针(一) shared_ptr
1. 几种智能指针 1. auto_ptr: c++11中推荐不使用他 2. shared_ptr: 每添加一次引用 就+1,减少一次引用,就-1:做到指针进行共享 3. unique_ptr: 一个 ...