题目链接: poj 1273
题目大意: 有N个点和M条边,每条边最大的流量为c,初始流量为0
1为源点,n为汇点求最大流
解题思路: 最短增广路算法比一般增广路算法每次增广大范围小,因为每次增广都在残留网络进行
但是最短增广路每次还是要回到源点继续增广,而连续最短增广路算法则利用深搜的思想
一次遍历就能把残留网络增广完毕
PS:用邻接表时要注意反向边也要加入,因为需要不断增广直到最优解
代码:
//网络最大流 Dinic算法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 400
#define INF 0x3f3f3f3f
#define Min(a,b) (a<b?a:b)
int n,m,edge[MAX][MAX],visit[MAX],pre[MAX],Index,Flag[MAX][MAX],Map[MAX][MAX];
int listb[MAX<<1];
struct snode{
int to,c,next;
}Edge[MAX*MAX*2];
void Add_Edge(int a,int b,int c)
{
Edge[Index].to=b;Edge[Index].c=c;
Edge[Index].next=pre[a];
pre[a]=Index++;
}
bool BFS() //BFS寻找容量网络
{
int i,s,e,v;
s=e=0;
memset(visit,0,sizeof(visit));
memset(Flag,0,sizeof(Flag));
visit[1]=1;
listb[s++]=1;
while(s!=e)
{
v=listb[e++];
if(v==n)
return true;
for(i=pre[v];i!=-1;i=Edge[i].next)
{
if(!visit[Edge[i].to]&&Map[v][Edge[i].to])
{
visit[Edge[i].to]=1;
Flag[v][Edge[i].to]=1;
listb[s++]=Edge[i].to;
}
}
}
return false;
}
int DFS(int Star,int sum) //Dinic
{
int v,t,i,s=sum;
if(Star==n||sum==0)
return sum;
for(i=pre[Star];i!=-1;i=Edge[i].next)
{
v=Edge[i].to;
if(Flag[Star][v])
{
t=DFS(v,Min(Map[Star][v],sum));
Map[Star][v]-=t;
Map[v][Star]+=t;
sum-=t;
}
}
return s-sum;
}
int Solve()
{
int sum=0;
while(BFS())
sum+=DFS(1,INF);
return sum;
}
int main()
{
int i,j,a,b,c;
while(scanf("%d%d",&m,&n)!=EOF)
{
memset(pre,-1,sizeof(pre));
memset(edge,0,sizeof(edge));
memset(Map,0,sizeof(Map));
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
edge[a][b]+=c;
Map[a][b]+=c;
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(edge[i][j]!=0)
{
Add_Edge(i,j,Map[i][j]);
Add_Edge(j,i,-Map[i][j]); //双向边
}
}
}
printf("%d\n",Solve());
}
}