网络流 之 dinic算法
我觉得这个dinic的算法和之前的增广路法差不多
、使用BFS对残余网络进行分层,在分层时,只要进行到汇点的层次数被算出即可停止,
因为按照该DFS的规则,和汇点同层或更下一层的节点,是不可能走到汇点的。 、分完层后,从源点开始,用DFS从前一层向后一层反复寻找增广路(即要求DFS的每一步都必须要走到下一层的节点)。 、DFS过程中,要是碰到了汇点,则说明找到了一条增广路径。此时要增加总流量的值,消减路径上各边的容量,
并添加反向边,即所谓的进行增广。 、DFS找到一条增广路径后,并不立即结束,而是回溯后继续DFS寻找下一个增广路径。回溯到的结点满足以下的条件: ) DFS搜索树的树边(u,v)上的容量已经变成0。即刚刚找到的增广路径上所增加的流量,等于(u,v)本次增广前的容量。
(DFS的过程中,是从u走到更下层的v的)
) u是满足条件 )的最上层的节点。 、如果回溯到源点而且无法继续往下走了,DFS结束。因此,一次DFS过程中,可以找到多条增广路径。
、DFS结束后,对残余网络再次进行分层,然后再进行DFS当残余网络的分层操作无法算出汇点的层次(即BFS到达不了汇点)时,
算法结束,最大流求出。 #include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e5;
struct edge
{
int u, v, c, f;
edge(int u, int v, int c, int f) :u(u), v(v), c(c), f(f) {}
};
vector<edge>e;
vector<int>G[maxn];
int level[maxn];//BFS分层,表示每个点的层数
int iter[maxn];//当前弧优化
int m;
void init(int n)
{
for (int i = ; i <= n; i++)G[i].clear();
e.clear();
}
void addedge(int u, int v, int c)
{
e.push_back(edge(u, v, c, ));
e.push_back(edge(v, u, , ));
m = e.size();
G[u].push_back(m - );
G[v].push_back(m - );
}
void BFS(int s)//预处理出level数组
//直接BFS到每个点
{
memset(level, -, sizeof(level));
queue<int>q;
level[s] = ;
q.push(s);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int v = ; v < G[u].size(); v++)
{
edge& now = e[G[u][v]];
if (now.c > now.f && level[now.v] < )
{
level[now.v] = level[u] + ;
q.push(now.v);
}
}
}
}
int dfs(int u, int t, int f)//DFS寻找增广路
{
if (u == t)return f;//已经到达源点,返回流量f
for (int &v = iter[u]; v < G[u].size(); v++)
//这里用iter数组表示每个点目前的弧,这是为了防止在一次寻找增广路的时候,对一些边多次遍历
//在每次找增广路的时候,数组要清空
{
edge &now = e[G[u][v]];
if (now.c - now.f > && level[u] < level[now.v])
//now.c - now.f > 0表示这条路还未满
//level[u] < level[now.v]表示这条路是最短路,一定到达下一层,这就是Dinic算法的思想
{
int d = dfs(now.v, t, min(f, now.c - now.f));
if (d > )
{
now.f += d;//正向边流量加d
e[G[u][v] ^ ].f -= d;
//反向边减d,此处在存储边的时候两条反向边可以通过^操作直接找到
return d;
}
}
}
return ;
}
int Maxflow(int s, int t)
{
int flow = ;
for (;;)
{
BFS(s);
if (level[t] < )return flow;//残余网络中到达不了t,增广路不存在
memset(iter, , sizeof(iter));//清空当前弧数组
int f;//记录增广路的可增加的流量
while ((f = dfs(s, t, INF)) > )
{
flow += f;
}
}
return flow;
}
接下来贴一个模板题,但是这个题目的图有点难建
C - Dining
Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others.
Farmer John has cooked fabulous meals for his cows, but he forgot to check his menu against their preferences. Although he might not be able to stuff everybody, he wants to give a complete meal of both food and drink to as many cows as possible.
Farmer John has cooked F (1 ≤ F ≤ 100) types of foods and prepared D (1 ≤ D ≤ 100) types of drinks. Each of his N (1 ≤ N ≤ 100) cows has decided whether she is willing to eat a particular food or drink a particular drink. Farmer John must assign a food type and a drink type to each cow to maximize the number of cows who get both.
Each dish or drink can only be consumed by one cow (i.e., once food type 2 is assigned to a cow, no other cow can be assigned food type 2).
Input
Lines 2.. N+1: Each line i starts with a two integers Fi and Di, the number of dishes that cow i likes and the number of drinks that cow i likes. The next Fiintegers denote the dishes that cow i will eat, and the Di integers following that denote the drinks that cow i will drink.
Output
Sample Input
4 3 3
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3
Sample Output
3
Hint
Cow 1: no meal
Cow 2: Food #2, Drink #2
Cow 3: Food #1, Drink #1
Cow 4: Food #3, Drink #3
The pigeon-hole principle tells us we can do no better since there are only three kinds of food or drink. Other test data sets are more challenging, of course.
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cstring>
#include <vector>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
int n, f, d;
struct node
{
int from, to, cap, flow;
node(int from = , int to = , int cap = , int flow = ) :from(from), to(to), cap(cap), flow(flow) {}
};
vector<node>e;
vector<int>G[maxn];
int level[maxn], iter[maxn];
void add(int u, int v, int w)
{
e.push_back(node(u, v, w, ));
e.push_back(node(v, u, , ));
int m = e.size();
G[u].push_back(m - );
G[v].push_back(m - );
} void bfs(int s)//这个是为了构建层次网络,也就是level的构建
{
memset(level, -, sizeof(level));
queue<int>que;
que.push(s);
level[s] = ;
while (!que.empty())
{
int u = que.front(); que.pop();
for (int i = ; i < G[u].size(); i++)
{
node &now = e[G[u][i]];
if (now.cap > now.flow&&level[now.to] < )//只有这个没有满并且没有被访问过才可以被访问
{
level[now.to] = level[u] + ;
que.push(now.to);
}
}
}
} int dfs(int u, int v, int f)
{
if (u == v) return f;
for (int &i = iter[u]; i < G[u].size(); i++)
{
node &now = e[G[u][i]];
if (now.cap > now.flow&&level[now.to] > level[u])
{
int d = dfs(now.to, v, min(f, now.cap - now.flow));
if (d > )
{
now.flow += d;
e[G[u][i] ^ ].flow -= d;
return d;
}
}
}
return ;
} int Maxflow(int s, int t)
{
int flow = ;
while ()
{
bfs(s);
if (level[t] < ) return flow;
memset(iter, , sizeof(iter));
int f;
while ((f = dfs(s, t, inf) > )) flow += f;
}
}
void init()
{
for (int i = ; i <= n + ; i++) G[i].clear();
e.clear();
} int main()
{
while (cin >> n >> f >> d)
{
init();
int s = , t = f + * n + d + ;
for (int i = ; i <= f; i++) add(s, i, );
for (int i = ; i <= n; i++)
{
int a, b;
cin >> a >> b;
while (a--)//与牛i相连
{
int x;
cin >> x;
add(x, f + i, );
}
add(f + i, f + n + i, );
while (b--)
{
int x;
cin >> x;
add(f + n + i, f + * n + x, );
}
}
for (int i = ; i <= d; i++) add(f + * n + i, t, );
int ans = Maxflow(s, t);
cout << ans << endl;
}
return ;
}
网络流 之 dinic算法的更多相关文章
- [知识点]网络流之Dinic算法
// 此博文为迁移而来,写于2015年2月6日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vrg4.html ...
- [无效]网络流之Dinic算法
// 此博文为迁移而来,写于2015年2月6日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vrg4.html UPDA ...
- 网络流之Dinic算法
初学网络流.存一下Dinic板子. 复杂度O(n^2*m) UVA - 1515 Pool construction 把每个草地与 S 相连,花费为dig,每个洞与 T 相连,花费为 然后对于每个两个 ...
- 网络流 之 dinic 算法
网络流指的是:网络流(network-flows)是一种类比水流的解决问题方法.(类似于水管群,有一个源点(水无限多),和一个汇点,最大流就代表这个点水管群(边集)每秒最大能送道汇点的水量) 这个怎么 ...
- Secret Milking Machine POJ - 2455 网络流(Dinic算法---广搜判断+深搜增广)+时间优化+二分
题意: 第一行输入N M C ,表示从1到N有M条无向边,现在要从1走到N 走C次完全不同的路径,求最长边的最小值.下面M行是从a点到b点的距离. 建图: 题上说从两点之间可以有多条边,问的是从1~N ...
- 网络流(dinic算法)
洛谷p3376 https://www.luogu.com.cn/problem/P3376 #include <iostream> #include <cstdio> #in ...
- 网络流最大流——dinic算法
前言 网络流问题是一个很深奥的问题,对应也有许多很优秀的算法.但是本文只会讲述dinic算法 最近写了好多网络流的题目,想想看还是写一篇来总结一下网络流和dinic算法以免以后自己忘了... 网络流问 ...
- 网络流入门—用于最大流的Dinic算法
"网络流博大精深"-sideman语 一个基本的网络流问题 最早知道网络流的内容便是最大流问题,最大流问题很好理解: 解释一定要通俗! 如右图所示,有一个管道系统,节点{1,2,3 ...
- Dinic算法(研究总结,网络流)
Dinic算法(研究总结,网络流) 网络流是信息学竞赛中的常见类型,笔者刚学习了最大流Dinic算法,简单记录一下 网络流基本概念 什么是网络流 在一个有向图上选择一个源点,一个汇点,每一条边上都有一 ...
随机推荐
- JavaScript面向对象--继承 (超简单易懂,小白专属)
一.继承的概念 子类共享父类的数据和方法的行为,就叫继承. 二.E55如何实现继承?探索JavaScript继承的本质 2.1构造函数之间的"复制粘贴" 第一条路是通过构造函数来继 ...
- Hbase王国游记之:Hbase客户端API初体验
§历史回顾 2018年岁末,李大胖朦胧中上了开往Hbase王国的车,伴着一声长鸣,列出缓缓驶出站台,奔向无垠的广袤. (图片来自于网络) 如不熟悉剧情的,可观看文章: 五分钟轻松了解Hbase列式存储 ...
- AppBoxFuture(二): Say goodbye to sql!
信息管理类应用系统离不开关系数据存储,目前大家基本都使用的是传统的数据库如MySql.Postgres等.作者从事信息化建设十多年,个人认为传统的数据库存在以下的问题: 扩展问题: 系统数据的 ...
- Java——多态浅析
前言 在面向对象程序设计语言中,多态是继数据抽象和继承之后的第三种基本特性.多态的含义是什么,有什么作用以及在Java中是怎么实现的?下面将做介绍. 什么是多态 简单点说就是"一个接口,多种 ...
- .net core EFCore CodeFirst 迁移出现错误【No project was found. Change the current working directory or use the --project option. 】
PM> dotnet ef Migrations add Init No project was found. Change the current working directory or u ...
- Linux,在不使用U盘的情况下使用wubi.exe程序在Win7上安装ubuntu-14.04.3版系统
本文介绍如何在不使用U盘的情况下使用wubi.exe程序在Win7上安装ubuntu-14.04.3版系统. 花了一天的时间终于安装上了Ubuntu14.04,过程坎坷,是血泪史,开始报“cannot ...
- 37.QT-QTSingleApplication-程序只运行一个实例
QTSingleApplication由Qt官方提供的,用于实现只启动一个实例,并在启动时可以向向另一个实例通信(依赖于QtNetwork模块) QTSingleApplication下载路径:链接: ...
- jsp基础语言-jsp声明
jsp声明的语法格式:<%! 声明代码 %> jsp声明的意义:用来定义在程序中使用到的变量.方法等.最后要以“:”结尾. jsp声明举例: <%! int a=100,b=200; ...
- [ArcGIS API for JavaScript 4.8] Sample Code-Get Started-widgets简介
[官方文档:https://developers.arcgis.com/javascript/latest/sample-code/intro-widgets/index.html] 一.Intro ...
- 36.Odoo产品分析 (四) – 工具板块(6) – 午餐管理(2)
查看Odoo产品分析系列--目录 接上一篇Odoo产品分析 (四) – 工具板块(6) – 午餐管理(1) 4 查看订单 点击"之前的订单",可以看到刚才的订单信息: 点击右边的 ...