网络流

P3376 网络流-最大流模板题(Dinic+当前弧优化)

耗尽温柔 提交于 2019-11-28 01:12:51
(点击此处查看原题) Dinic算法 Dinic算法相对于EK算法,主要区别在于Dinic算法对图实现了分层,使得我们可以用一次bfs,一次dfs使得多条增广路得到增广 普通的Dinic算法已经可以处理绝大多数最大流(最小割)的题目了,但是总是有些题目会卡住普通的Dinic算法,此时我们就需要用到当前弧优化了 当前弧优化简述 不要小看当前弧优化,这个优化效果可是很明显的,就这个例题来说,我用普通的Dinic算法用时约1.7s,而使用了当前弧优化的Dinic算法后,只用了176ms,由此可以看出这个优化的强大 当前弧优化的核心思想为:避免遍历已经满流的边,总所周知,已经满流的边已经再构成增广路,而普通Dinic算法中,我们总是遍历所有的边,后判断这条边是否满流,这样相当于白白消耗时间 回想一下我们普通Dinic算法中将增广路增广的方法:我们总是尽可能地将某一条边的容量完全利用,因为我们建立了反边,可以“反悔”,因此我们可以完全利用这条边的容量;而对于被完全利用的边,因为这条边已经满流了,之后的增广路中不会用到这条边,那么我们就可以标记一下从每个点出发的第一条不满流边,下次从这个点开始求增广路的时候,就可以跳过之前已经满流的那些边,直接从不满流边开始遍历了 具体操作的话,我们用cur数组记录以每个点为起点的边当前可用的第一条不满流边,在dfs之前我们将head数组的值复制给cur数组

[网络流24题(5/24)] 分配问题(最小费用最大流)

十年热恋 提交于 2019-11-27 21:54:53
传送门 分析: 非常经典的费用流的模型吧,也可以通过二分图最大匹配去做,但是鉴于二分图最大匹配的算法存在一定的局限性,故还是学一学较为通用的费用流的做法。 这道题目中本质上要讨论的问题跟运输问题, 运输问题 是一致的。 因为考虑到每个人只能被分配到一种货物,每种货物只能被一个人所分配,因此,我们不妨用流量将他们限流。 我们创建一个超级源地 \(sp\) ,将 \(sp\) 跟每个人连一条流量为 \(1\) ,费用为 \(0\) 的边。 同时我们创建一个超级汇点 \(ep\) ,将每一种货物跟 \(ep\) 都连一条流量为 \(1\) ,费用为 \(0\) 的边。 同时,对于每一个人和货物,我们对他们连一条流量为无穷的边。 因为每个人只能从超级源点获取最多 \(1\) 点的流量,每种货物只能向超级汇点传送最多 \(1\) 点的流量,因此当这个图满流时,能够保证每个人一定会配对最多一个货物,即达到我们限流的要求。 而如果我们需要求解最小花费,我们只需要将人和货物的边加上的费用取 \(val_{ij}\) ,最后在这张图上跑最小费用最大流后最小费用即为答案。 而如果我们需要求解最大花费,我们只需要将人和货物的边加上的费用取相反数 \(-val_{ij}\) ,最后在这张图上跑最小费用最大流后最小费用的相反数即为答案。 代码: #include <bits/stdc++.h>

2019暑假集训 8/17

血红的双手。 提交于 2019-11-27 16:43:29
学习内容 :网络流 今日完成题数(不包含多校) : 今日看书情况 :无 学习算法的总结 有上下界的网络流 和 最小费用可行流 今日做题总结 https://www.cnblogs.com/MengX/p/11370478.html https://www.cnblogs.com/MengX/p/11369209.html 今日心得: 学会了上下界网络流 明日任务: 明天整下多校的网络流题 来源: https://www.cnblogs.com/MengX/p/11370587.html

hdu6437 Problem L.Videos(网络流)

对着背影说爱祢 提交于 2019-11-27 16:39:08
Problem L.Videos Problem Description: C-bacteria takes charge of two kinds of videos: ’The Collection of Silly Games’ and ’The Collection of Horrible Games’. For simplicity’s sake, they will be called as videoA and videoB. There are some people who want to watch videos during today, and they will be happy after watching videos of C-bacteria. There are n hours a day, m videos are going to be show, and the number of people is K. Every video has a type(videoA or videoB), a running time, and the degree of happi- ness after someone watching whole of it. People can watch videos continuous(If one

【网络流】——P2756 飞行员配对方案问题

这一生的挚爱 提交于 2019-11-27 16:34:27
简单的二分图匹配问题。 GO: 洛谷 水水就过了。 配对方案从边里面找: 一定是权值为0的边 源点一定在1~m间,汇点一定在m+1~n间 直接输出即可。 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1100; 4 const int inf=1e9; 5 int m,n,S,T,cnt=-1,maxflow; 6 int d[N],head[N<<1]; 7 struct edge{int to,next,f,from;}e[N<<1]; 8 void addedge(int from,int to,int f){e[++cnt]=(edge){to,head[from],f,from};head[from]=cnt;} 9 inline bool bfs(){ 10 memset(d,0,sizeof(d)); 11 queue<int>q; 12 q.push(S); 13 d[S]=1; 14 while(q.size()){ 15 int u=q.front(); 16 q.pop(); 17 for(int i=head[u];i!=-1;i=e[i].next){ 18 int v=e[i].to,f=e[i].f; 19 if(d[v]||!f) continue; 20 d[v]=d

网络流初步

一个人想着一个人 提交于 2019-11-27 15:56:24
其实网络流很久之前已经学过,但是因为一些原因搁置了很久,于是想再系统地复习一下. 由于博主能力有限,所以关于网络流知识也是了解个大概,这里只是简单介绍,并且说一下博主的 感性理解 最大流   EK増广路算法     很容易理解的一个算法,也就是我们不断地bfs找出一条増广路然后更新剩余容量,直到更新完毕,类似于SPFA做法.时间复杂度$O(nm^{2})$;     这里不再附上代码,因为后面的费用流就要用EK+SPFA,而只是求最大流,推荐Dinic.   Dinic算法     与EK不同的是,Dinic算法增加了一些优化,这里引进了深度这个概念,通过在同一深度图中増广,一个点可以向多个点进行多流増广,并有减枝;     于是Dinic就可以达到$O(n^{2}m)$的优秀时间复杂度,可以代替匈牙利算法跑二分图匹配,时间复杂度$O(n\sqrt{n})$;     PS:关于二分图匹配时间复杂度可以这么想,由于一个点多流推进,同时増广多个点,而且深度小,所以时间复杂度就十分优秀;     Code:      #include<bits/stdc++.h> #define maxn 10008 using namespace std; int n,m,head[maxn],s,t,cent=1,d[maxn],maxflow; int min(int a,int b)

【网络流】——P2764 最小路径覆盖问题

人盡茶涼 提交于 2019-11-27 15:17:27
一个最小路径覆盖的模板题。 Go: 洛谷 最小路径覆盖=顶点数-二分图最大匹配 因此我们将点复制一份,按照题目给的数据在两端连边,长度为1。 建立一个super源&汇,源向左边的点连边,右边的点向汇连边,长度为1。 求解路径: 我们在邻接表中存下每条边的起始点,对于一条流为0的边,表示它是最小路径中的一条,那么用冰茶姬将他们连起来,最后访问单独集合中的路径即可。 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 6e5+10,inf = 1e9; 4 int n, m, S, T, ans, d[N],head[N],maxflow,vis[N],f[N]; 5 int tot=-1; 6 struct edge{ 7 int w; 8 int next; 9 int to; 10 int from; 11 }e[N]; 12 int getf(int x){ 13 return f[x]==x?f[x]:f[x]=getf(f[x]); 14 } 15 inline void addedge(int x, int y, int z) { 16 e[++tot].to=y; 17 e[tot].next=head[x]; 18 e[tot].w=z; 19 e[tot].from=x; 20 head