博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
有源汇有上下界可行流/最大流
阅读量:5273 次
发布时间:2019-06-14

本文共 2700 字,大约阅读时间需要 9 分钟。

解析为转载 :https://www.cnblogs.com/liu-runda/p/6262832.html   博主讲的挺好的
有源汇有上下界可行流
模型:现在的网络有一个源点s和汇点t,求出一个流使得源点的总流出量等于汇点的总流入量,其他的点满足流量守恒,而且每条边的流量满足上界和下界限制.
源点和汇点不满足流量守恒,这让我们很难办,因此我们想办法把问题转化成容易处理的每个点都满足流量守恒的无源汇情况.
为了使源汇点满足流量守恒,我们需要有边流入源点s,有边流出汇点t.注意到源点s的流出量等于汇点t的流入量,我们就可以从汇点t向源点s连一条下界为0上界为无穷大的边,相当于把从源点s流出的流量再流回来.在这样的图中套用上面的算法求出一个可行的循环流,拆掉从汇点t到源点s的边就得到一个可行的有源汇流.
这里有一个小问题:最后得到的可行的有源汇流的流量是多少?
可以发现,循环流中一定满足s流出的总流量=流入s的总流量,假定原图中没有边流入s,那么s流出的流量就是t到s的无穷边的流量,也就是s-t可行流的流量.因此我们最后看一下t到s的无穷边的流量(即dinic跑完之后反向边的权值)即可知道原图中有源汇可行流的流量.
 
 
例题:LOJ 116 :https://loj.ac/problem/116
 
#include 
#include
#include
#include
#define mem(a,b) memset(a,b,sizeof(a))using namespace std;const int maxn = 100010, INF = 0x7fffffff;int d[maxn], head[maxn], in[maxn];int n, m, s, t;struct node{ int u, v, c, f, next, bz; //bz为标记是否为原图中的路 1 是 0 不是}Node[maxn];void add(int u, int v, int c, int f,int i, int bz){ Node[i].u = u; Node[i].v = v; Node[i].c = c; Node[i].f = f; Node[i].next = head[u]; head[u] = i; Node[i].bz = bz;}int bfs(){ queue
Q; mem(d,0); Q.push(s); d[s] = 1; while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i=head[u]; i!=-1; i=Node[i].next) { node e = Node[i]; if(!d[e.v] && e.c > e.f) { d[e.v] = d[e.u] + 1; Q.push(e.v); } } } return d[t] != 0;}int dfs(int u, int cap){ if( u == t) return cap; for(int i=head[u]; i!=-1; i=Node[i].next) { node e = Node[i]; if(d[e.v] == d[e.u] + 1 && e.c > e.f) { int V = dfs(e.v, min(cap, e.c - e.f)); if(V > 0) { Node[i].f += V; Node[i^1].f -= V; return V; } } } return 0;}int Dinic(int u){ int ans = 0; while(bfs()) { while(int l = dfs(u, INF)) ans += l; } return ans;}int main(){ mem(head,-1); int s_, t_; //源点和汇点 cin>> n >> m >> s_ >> t_; s = 0; t = n+1; // 设置超级源点 和 超级汇点 int sum = 0, cnt = 0; for(int i=0; i
> u >> v >> b >> d; add(u, v, d-b, 0, cnt++,1); add(v, u, 0, 0, cnt++,1); in[v] += b; in[u] -= b; } for(int i=1; i<=n; i++) { if(in[i] > 0) { sum += in[i]; add(s,i,in[i],0,cnt++,0); add(i,s,0,0,cnt++,0); } else { add(i,t,-in[i],0,cnt++,0); add(t,i,0,0,cnt++,0); } } add(t_,s_,INF,0,cnt++,0); //连接汇点和源点 上界为无穷大 下界为0 add(s_,t_,0,0,cnt++,0); if(sum != Dinic(s)) //如果不等于 说明没有可行流 { cout<< "please go home to sleep" <

 

转载于:https://www.cnblogs.com/WTSRUVF/p/9196034.html

你可能感兴趣的文章
typeset shell 用法
查看>>
python 之 循环语句
查看>>
心得25--JDK新特性9-泛型1-加深介绍
查看>>
[转]ceph网络通信模块_以monitor模块为例
查看>>
HDOJ 1754 I Hate It(线段树基本操作)
查看>>
latex tree
查看>>
安装NVIDIA驱动时禁用自带nouveau驱动
查看>>
HDU-1255 覆盖的面积 (扫描线)
查看>>
【USACO】 奶牛会展
查看>>
继承和多态
查看>>
Dijkstra+计算几何 POJ 2502 Subway
查看>>
修复IE不能执行JS的方法
查看>>
程序员究竟该如何提高效率zt
查看>>
希尔排序法(缩小增量法)
查看>>
PHP编程基础学习(一)——数据类型
查看>>
MongoDB-JAVA-Driver 3.2版本常用代码全整理(2) - 查询
查看>>
NPOI处理Word文本中上下角标
查看>>
Android笔记 Handler
查看>>
如何阅读大型前端开源项目的源码(转)
查看>>
java.util.Arrays类详解
查看>>