Dinic算法(网络流,最大流)
2016-08-12 11:37
411 查看
Dinic算法是用来解决网络流问题的经典算法,时间效率很快,还可以支持重边。下面让我来介绍一下Dinic算法。
首先,定义弧:
Dinic算法就是不断用BFS构造层次图,然后用DFS进行增广。那么,什么是层次图呢?
设dist(u)为原点s到节点u的距离,那么,层次图就是只保留满足dist(u)+1 = dist(u1)的边(u,u1)。
这是一个层次图。
而层次图可以用BFS在残留网络的基础上构造。
假如还存在s-t的路径,我们为了方便,可以用DFS进行多路增广。DFS过程出了当前节点以外,还要看看目前所有弧的最小残量a是否为0,当x为汇点或a为0是终止DFS。
首先,定义弧:
struct edge{ int from , to , cap , flow; };
Dinic算法就是不断用BFS构造层次图,然后用DFS进行增广。那么,什么是层次图呢?
设dist(u)为原点s到节点u的距离,那么,层次图就是只保留满足dist(u)+1 = dist(u1)的边(u,u1)。
这是一个层次图。
而层次图可以用BFS在残留网络的基础上构造。
bool BFS() { memset(vis,0,sizeof(vis)); queue<int> q;//模拟BFS q.push(s); d[s] = 0; vis[s] = 1; while(!q.empty())//队列非空 { int x = q.front(); q.pop(); for(int i=0;i<f[x].size();i++) { edge &e = edges[f[x][i]]; if(!vis[e.to] && e.flow < e.cap) //只考虑残留网络中的弧 { vis[e.to] = 1; d[e.to] = d[x] + 1;//层次图 q.push(e.to); } } } return vis[t];//能否到汇点,不能就结束 }
假如还存在s-t的路径,我们为了方便,可以用DFS进行多路增广。DFS过程出了当前节点以外,还要看看目前所有弧的最小残量a是否为0,当x为汇点或a为0是终止DFS。
int DFS(int x,int a)//x为当前节点,a为当前最小残量 { if(x == t || a == 0) return a; int flow = 0 , r; for(int& i = cur[x];i < f[x].size();i++) { edge& e = edges[f[x][i]]; if(d[x] + 1 == d[e.to] && (r = DFS(e.to , min(a,e.cap - e.flow) ) ) > 0 ) { e.flow += r; edges[f[x][i] ^ 1].flow -= r; flow += r;//累加流量 a -= r; if(a == 0) break; } } return flow; }至此,整个Dinic算法都清晰了。下面给出程序:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int Maxn = 10000 + 10;
const int INF = 0x6fffffff >> 2;
struct edge{ int from , to , cap , flow; };
struct Dinic{
int n,m,s,t;
vector<edge> edges;
vector<int> f[Maxn];
bool vis[Maxn];
int d[Maxn];
int cur[Maxn];
void AddEdge(int from,int to,int cap)
{
edges.push_back((edge){from,to,cap,0});
edges.push_back((edge){to,from,0,0});
m = edges.size();
f[from].push_back(m-2);
f[to].push_back(m-1);
}
bool BFS()
{
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(s);
d[s] = 0;
vis[s] = 1;
while(!q.empty())
{
int x = q.front(); q.pop();
for(int i=0;i<f[x].size();i++)
{
edge &e = edges[f[x][i]];
//cout<<"to="<<e.to<<"from="<<e.from<<' '<<e.flow<<' '<<e.cap<<' '<<vis[e.to]<<endl;
if(!vis[e.to] && e.flow < e.cap) //只考虑残留网络中的弧
{
vis[e.to] = 1;
d[e.to] = d[x] + 1;//层次图
q.push(e.to);
}
}
}
return vis[t];//能否到汇点,不能就结束
}
int DFS(int x,int a)//x为当前节点,a为当前最小残量 { if(x == t || a == 0) return a; int flow = 0 , r; for(int& i = cur[x];i < f[x].size();i++) { edge& e = edges[f[x][i]]; if(d[x] + 1 == d[e.to] && (r = DFS(e.to , min(a,e.cap - e.flow) ) ) > 0 ) { e.flow += r; edges[f[x][i] ^ 1].flow -= r; flow += r;//累加流量 a -= r; if(a == 0) break; } } return flow; }
int MaxFlow(int s,int t)
{
this->s = s; this->t = t;
int flow = 0;
while(BFS())
{
memset(cur,0,sizeof(cur));
flow += DFS(s,INF);
}
return flow;
}
}G;
int main()
{
int x,y,z;
int s,t;
scanf("%d",&G.n);
while(1)
{
scanf("%d%d%d",&x,&y,&z);
if(!(x|y|z)) break;
G.AddEdge(x,y,z);
}
scanf("%d%d",&s,&t);
printf("%d\n",G.MaxFlow(s,t));
return 0;
}
相关文章推荐
- poj 1273 hdu 1532 网络流最大流 Dinic算法
- (模板)网络流最大流,dinic算法
- 最大网络流模板Dinic算法
- 最大网络流dinic算法—【hdoj1532】Drainage Ditches
- 网络流入门—用于最大流的Dinic算法
- 网络流初步:最大流(Dinic算法)
- 最大网络流Dinic算法(逆序广搜构造分层网络)
- poj 1459 Power Network : 最大网络流 dinic算法实现
- poj 1459 Power Network : 最大网络流 dinic算法实现
- 网络流入门 最大流,带下界,最小费用,EK算法,Dinic算法 模板
- Power Network(网络流最大流 & dinic算法 + 优化)
- 网络流入门—用于最大流的Dinic算法---转载自Comzyh的博客
- 网络流入门—用于最大流的Dinic算法
- 网络流入门—用于最大流的Dinic算法
- 最大网络流Dinic算法
- [译]网络流Dinic算法-最大流-HDU1532&POJ1273
- 最大网络流Dinic算法(优化版)
- 网络流入门—用于最大流的Dinic算法
- 网络流入门—用于最大流的Dinic算法
- hdu4280 Island Transport (网络流最大流)&(dinic算法模板)