dinic算法 c 语言,网络流Dinic算法详解及模板
/*****以下来自<> 王欣*****/
层次图
短路增值算法(MPLA)
算法流程
汇点不在层次图内意味着在剩余图中不存在一条从源点到汇点的路径,即没有增广路。
在程序实现的时候,层次图并不用被“建”出来,我们只需对每个顶点标记层次,增广的时候,判断边是否满足level(u) +1= level(v)这一约束即可。
Dinic算法
Dinic算法的思想也是分阶段地在层次图中增广。
它与最短路径增值算法不同之处是:在Dinic算法中,我们用一个dfs过程代替多次bfs来寻找阻塞流。下面给出其算法步骤:
算法流程
增广过程图解
伪代码描述
在程序里,p表示找到的增广路径,p.top为路径中的最后一个顶点。一开始,p中只有源点。
整个While循环分为2个操作。如果p的最后一个顶点为汇点,也就是说找到了增广路,那么对p增广,注意到增广后一定有一条或多条p中的边被删除了。这时,我们使增广路径后退至p中从源点可到达的最后一个顶点。
如果p的最后一个顶点不为汇点,那么观察最后那个的顶点u 。若在层次图中存在从u连出的一条边,比如(u,v),我们就将顶点v放入路径p中,继续dfs遍历;否则,点u对之后的dfs遍历就没有用了,我们将点u以及层次图中连到u的所有边删除,并且在p中后退一个点。
Dfs过程将会不断重复这2个操作,直到从源点连出的边全部被删除为止。
/*****以上来自<> 王欣*****/
模板
/* filename :network_flow_Dinic.cpp
* author :AntiheroChen
* Description :It's a Dinic solution for the network flow prblem.
* Complexity :O(V^2*E) always below this.
* Version :1.00
* History :
* 1)2012/02/29 first release.
*/
#include
#include
#include
#include
using namespace std;
const int maxn=1000+5, bign=1000000000;
int M, n, m, source, sink, c[maxn][maxn], cnt[maxn];
/* The arc of the flow network.*/
struct Pool
{
int next, t, c;
} edge[maxn*maxn<<1];
/* The point of the flow network.*/
struct Point
{
int son, cur, pre, lim, d;
} a[maxn];
/* Prepare for the algorithm.*/
void initialize()
{
M=1;
memset(c, 0, sizeof (c));
memset(a, 0, sizeof (a));
memset(cnt, 0, sizeof (cnt));
}
/* Add an arc to the flow network.*/
void add(int x, int y, int z)
{
edge[++M].t=y;
edge[M].c=z;
edge[M].next=a[x].son;//相当于pool的head数组
a[x].son=M;
}
/* Read the data and make it the right format.*/
void input()
{
scanf("%*s%*d%d%d%d%d", &n, &m, &source, &sink);
initialize();
int x, y, z;
while (m--)
scanf("%d%d%d", &x, &y, &z), c[x][y]+=z;
for (int i=0; i
for (int j=0; j
if (c[i][j])add(i, j, c[i][j]), add(j, i, c[j][i]), c[j][i]=0;
}
int que[maxn], fi, la;
bool vis[maxn];
/* Build the hierarchical graph for the algorithm*/
bool build()
{
memset(vis, 0, sizeof (vis));
que[fi=la=0]=sink;//reverse
a[sink].d=0, a[sink].cur=a[sink].son, vis[sink]=true;
while (fi<=la)
{
int v=que[fi++];
for (int now=a[v].son, u; u=edge[now].t, now; now=edge[now].next)
if (edge[now^1].c&&!vis[u])//BFS来分层,这里和EK相同
{//倒着BFS的话,当然引用的还是对侧边,即正向边
a[u].d=a[v].d+1;//越向前标号渐大
a[u].cur=a[u].son;//cur指向头
vis[u]=true;//已遍历
que[++la]=u;//入队
}
if (vis[source])return true;//层次图向前已经扩展到原点
}
return false;
}
/*Use the Dinic algorithm to calculate the max flow.*/
int MaxFlow()
{
int u, v, now, ret=0;
while (build())
{
a[u=source].lim=bign;
while (true)
{
for (now=a[u].cur; v=edge[now].t, now; now=edge[now].next)//cur优化
if (edge[now].c&&a[u].d==a[v].d+1)break;//找到了一个子节点属于层次图
if (now)
{
a[u].cur=edge[now].next;//下一次从这一条边的下一条边开始dfs
a[v].pre=now;//指向v的边的指针
a[v].lim=min(a[u].lim, edge[now].c);///更新到此处为止流的上限
if ((u=v)==sink)//如果已经找到了一条增广路(走到了尽头)
///注意这个地方借判断语句, 将u下移, 便于判断为否的时候回到上面进入下一层!
{//进行增广
do
{
edge[a[u].pre].c-=a[sink].lim;
edge[a[u].pre^1].c+=a[sink].lim;//这两句和Edmonds-Karp是一样的,增广
u=edge[a[u].pre^1].t;//找前驱~!
} while (u!=source);
ret+=a[sink].lim;//增广完毕之后累加新找到的流
}//否则(没走到尽头)继续向下DFS
}
else//没有子节点属于层次图
{
if (u==source)break;//已经退到了源,则已找到最大流,算法结束
a[u].cur=now;//=0,此节点被废弃,子代亦然
u=edge[a[u].pre^1].t;//根据反向边找到前驱~!
}
}
}
return ret;
}
int main()
{
int total;
scanf("%d", &total);
while (total--)
{
input();
printf("%d\n", MaxFlow());
}
return 0;
}
dinic算法 c 语言,网络流Dinic算法详解及模板相关推荐
- 【JVM】对象存活判定算法、GC算法、STW、GC种类详解
[JVM]对象存活判定算法.GC算法.STW.GC种类详解 文章目录 [JVM]对象存活判定算法.GC算法.STW.GC种类详解 GC主要关注的区域 垃圾标记阶段:对象存活判断 标记阶段:引用计数算法 ...
- 大白话解析Apriori算法python实现(含源代码详解)
大白话解析Apriori算法python实现(含源代码详解) 一.专业名词解释 二.算法思路 三.python代码实现 四.Aprioir的优点.缺点及改进方法 本文为博主原创文章,转载请注明出处,并 ...
- JAVA中希尔排序去的讲解_java 中基本算法之希尔排序的实例详解
java 中基本算法之希尔排序的实例详解 希尔排序(Shell Sort)是插入排序的一种.也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法.该方法因DL.Shel ...
- EM算法(Expectation Maximization Algorithm)详解
EM算法(Expectation Maximization Algorithm)详解 主要内容 EM算法简介 预备知识 极大似然估计 Jensen不等式 EM算法详解 问题描述 EM算法推导 EM ...
- 蓝桥杯 试题 算法训练 无聊的逗 C++ 详解
题目: 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的 ...
- 蓝桥杯 试题 算法训练 无聊的逗 C++ 详解 - 未完善
题目: 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的 ...
- 【目标检测算法-锚框公式推导及代码详解】
目标检测算法-锚框公式推导及代码详解 0 沐神对锚框的宽高计算并未推导以及讲解 1 锚框宽高公式推导 1.1 基础概念 1.2 锚框宽高公式推导 1.3 图片验证计算 1.4 小结 2 代码详解 2. ...
- c语言背包问题装字母,C语言动态规划之背包问题详解
01背包问题 给定n种物品,和一个容量为C的背包,物品i的重量是w[i],其价值为v[i].问如何选择装入背包的物品,使得装入背包中的总价值最大?(面对每个武平,只能有选择拿取或者不拿两种选择,不能选 ...
- c语言菜单选择如何用字符形式,【创客天地】计算机二级C语言、VB考试详解分析...
原标题:[创客天地]计算机二级C语言.VB考试详解分析 01 马上就要迎来计算机二级考试了,你准备好了吗?今天助手君准备了一点C语言干货,希望对即将考试的你有所帮助.(上期刚刚推了office,有需要 ...
- c语言比特和字节,详解 比特(位,bit),字节(Byte),字符的区别 *(转)
比特(位):英文bit,是计算机晶体管的一种状态(通电与断电).就是0与1,真与假,是计算机最基本的传输单位. 示例: 2bit : 10; 4bit : 1111; 8bit : 1111 1111 ...
最新文章
- DevOps时代测试应该如何应对?
- 【FPGA】单端口RAM的设计(异步读、同步写)
- Vue013_ vue组件化编码
- python字典顺序遍历_在Python中,如何按已排序的键顺序遍历字典?
- leetcode1386. 安排电影院座位(贪心)
- 005木桶缩放(比例非原始)
- break和continue区别python_1、Python中break和continue的区别
- try-catch-finally的返回值问题
- spring ioc控制反转
- centos7.6 安装nginx-1.14.2
- 综合评价模型的缺点_【必备】目标检测中的评价指标有哪些?
- 使用数据集(DataSet)、数据表(DataTable)、集合(Collection)传递数据
- python 波浪号用法_「波浪号」matlab中波浪号~的作用和用法 - 金橙教程网
- (六十五)for循环
- python :alpha shapes 算法检测边界点
- 贴吧老矣,尚能饭否?
- web程序中的用户注册
- 用matlab画标准雷电波,雷电波发生器的MATLAB仿真及参数选取sc.doc
- 蓝奏云分享链接打不开的问题解决
- win10运行在哪里打开 win10怎么打开运行窗口快捷键