网络流
目录
另一篇整理的博客
网络流简介
POJ 1273 Drainage Ditches
题意:给定点数,边数,每条 边的容量,以及源点,汇点,求最大流。
#include<iostream>
#include<queue>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn=300;
int G[maxn][maxn];
int Prev[maxn];//存放节点的前驱结点,方便加反向边
bool Visited[maxn];
int n,m;
/*从结点1开始压入栈中,然后寻找增广路径,并且用Prev来记录结点的前驱结点,找到一条增广路径之后,就开始求最大流
求完最大流之后,再加反向边修改图G。
*/
int Augment()
{
deque<int>q;
memset(Prev,0,sizeof(Prev));
memset(Visited,0,sizeof(Visited));
Prev[1]=0;
Visited[1]=1;
q.push_back(1);
bool bFindPath=false;
int v;
while(!q.empty())
{
v=q.front();
q.pop_front();
for(int i=1;i<=m;i++)
{
if(G[v][i]>0 && Visited[i]==0)
{
Prev[i]=v;
Visited[i]=1;
if(i==m)
{
bFindPath=true;
q.clear();
break;
}else{
q.push_back(i);
}
}
}
}
if(!bFindPath)
return 0;
int nMinFlow=999999999;
v=m;
while(Prev[v])
{
nMinFlow=min(nMinFlow,G[Prev[v]][v]);
v=Prev[v];
}
v=m;
while(Prev[v])
{
G[Prev[v]][v]-=nMinFlow;
G[v][Prev[v]]+=nMinFlow;//加反向边
v=Prev[v];
}
return nMinFlow;
}
int main()
{
while(cin>>n>>m)
{
int s,e,c;
memset(G,0,sizeof(G));
for(int i=0;i<n;i++)
{
cin>>s>>e>>c;
G[s][e]+=c;
}
int MaxFlow=0;
int aug;
while(aug=Augment())
{
MaxFlow+=aug;
}
cout<<MaxFlow<<endl;
}
return 0;
}
增广路径的优化--------->Dinic
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<deque>
#include<string.h>
using namespace std;
#define INF 999999999
const int maxn=300;
int G[maxn][maxn];
bool Visited[maxn];
int Layer[maxn];//分层数组
int n,m;
bool CountLayer()
{
int layer=0;
deque<int>q;
memset(Layer,0xff,sizeof(Layer));
Layer[1]=0;
q.push_back(1);
while(!q.empty())
{
int v=q.front();
q.pop_front();
for(int j=1;j<=m;j++)
{
if(G[v][j]>0 && Layer[j]==-1)
{
Layer[j]=Layer[v]+1;
if(j==m) //如果已经找到了汇点
return true;
else
q.push_back(j);
}
}
}
return false;
}
int Dinic()
{
int s;
int nMaxFlow=0;
deque<int>q;
while(CountLayer())
{
q.push_back(1);
memset(Visited,0,sizeof(Visited));
Visited[1]=1;
while(!q.empty())
{
int nd=q.back();
if(nd==m)//nd是汇点
{
int nMinC=INF;//最小流量
int nMinC_vs;//容量最小的边的起点
for(int i=1;i<q.size();i++)
{
int vs=q[i-1];
int ve=q[i];
if(G[vs][ve]>0)
{
if(nMinC>G[vs][ve])
{
nMinC=G[vs][ve];
nMinC_vs=vs;
}
}
}
nMaxFlow+=nMinC;
for(int i=1;i<q.size();i++)
{
int vs=q[i-1];
int ve=q[i];
G[vs][ve]-=nMinC;
G[ve][vs]+=nMinC;
}
while(!q.empty() && q.back()!=nMinC_vs)
{
Visited[q.back()]=0;
q.pop_back();
}
}else{ //不是汇点
int i;
for( i=1;i<=m;i++)
{
if(G[nd][i] >0 && Layer[i]==Layer[nd]+1 && !Visited[i])
{//往下一层没有走过的结点走
Visited[i]=1;
q.push_back(i);
break;
}
}
if(i>m)//找不到下一个节点
q.pop_back();//回溯
}
}
}
return nMaxFlow;
}
int main()
{
while(cin>>n>>m)
{
int s,e,c;
memset(G,0,sizeof(G));
for(int i=0;i<n;i++)
{
cin>>s>>e>>c;
G[s][e]+=c;
}
cout<<Dinic()<<endl;
}
return 0;
}