题目描述:有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给出这n条水渠所连接的池塘和所能流过的水量,求水渠中所能流过的水的最大容量.一道基础最大流题目
所用算法:dinic
算法描述:写最大流有EK算法和dinic算法。开始先学的是EK 算法,由于时间所迫吧,只能从这两个算法之中选取一个作为常解决问题的一个算法。所了解,dinic在数据较大时比EK高效,所以选取了dinic。此算法用到广搜和深搜的结合,用一次BFS 找出层次网络,然后在所找的层次网络中用DFS搜索增广路。这道题其实就是dinic模板题,所做的所有最大流题目中,并没有接触到算法的变形,有的只是问题的模型化和建图的难点。所以在这里简单介绍下算法能解决的具体问题吧,可能随着以后的锻炼,会有新的领悟并在此更新。
问题描述:问题中描绘的是一个有向图的模型,根据算法的需要,需要把图建为双向图(和无向图含义有所区别)。在这个图中可能有多个源点和汇点,也可能只有一个源点和汇点,一般情况下都化为一个源点和汇点。在这个双向图中每条边都有各自的管道容量,当然是单向的容量,反向的容量为0,所求流到汇点时的最大流量。
#include<stdio.h>
#include<queue>
#include<iostream>
#include<string.h>
using namespace std;
#define N 210
#define INF 0x3f3f3f3f
int n,m,k,s,t;
int head[N],d[N];
struct E
{
int u,v,c,next;
}edge[N<<1];
void addedge(int u,int v,int c)
{
edge[k].u=u;
edge[k].v=v;
edge[k].c=c;
edge[k].next=head[u];
head[u]=k++;
edge[k].u=v;
edge[k].v=u;
edge[k].next=head[v];
head[v]=k++;
}
int min(int a,int b)
{
return a<b?a:b;
}
int bfs()
{
int i,cur;
memset(d,-1,sizeof(d));
queue<int> q;
d[s]=0;
q.push(s);
while(!q.empty())
{
cur=q.front();
q.pop();
for(i=head[cur];i!=-1;i=edge[i].next)
{
if(d[edge[i].v]==-1&&edge[i].c>0)
{
d[edge[i].v]=d[cur]+1;
q.push(edge[i].v);
}
}
}
if(d[t]<0)
return 0;
return 1;
}
int dinic(int x,int flow)
{
int i,a;
if(x==t)
return flow;
int sum=flow;
for(i=head[x];i!=-1;i=edge[i].next)
{
if(d[edge[i].v]==d[x]+1&&edge[i].c>0)
{
a=dinic(edge[i].v,min(edge[i].c,sum));
edge[i].c-=a;
edge[i^1].c+=a;
sum-=a;
}
}
return flow-sum;
}
void solve()
{
int ans=0,increment;
while(bfs())
{
increment=dinic(1,INF);
ans+=increment;
}
cout<<ans<<endl;
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
int i,u,v,c;
k=0;
s=1;
t=n;
memset(head,-1,sizeof(head));
for(i=0;i<m;i++)
{
cin>>u>>v>>c;
addedge(u,v,c);
}
solve();
}
return 0;
}