一开始怎么也看不懂网络流,完全不明白那算法是怎么样的,直接导致我许多天没写代码了。。。今天终于上手了,\欢呼\撒花\。。。
准确来说,今天有了一点思路(虽然最后还是照着别人的代码敲了一遍,囧。。。)
这是简单的最大流问题,需要考虑的是有多重边需要注意,所以我们的做法是在原基础上加上重边上的容量。
最大流,我们用bfs寻找增广路,其中add数组表示增广路上的最小值(当然增广路来源于残存网络),pre数组记录当前点之前到达的点,这样,如果m点存在于增广路之中,那么pre[m]保存的就是之前的点,以此类推,直到起始点,则这条路就是增广路。当寻找不到增广路时,就说明已经得到最大流了。
之前一直不明白为什么这样就可以,总是认为会陷入死循环,不过从资料上(忘记是博客还是书上看到的了)看到,只要直到每次寻找增广路且更新flow之后,源点和汇点的值都增大,就能够想明白不会死循环~~似乎讲的不是很清楚,算了,这个略过。。不知道怎么说
值得一提的是,flow的更新我想了很久,终于明白了,弱弱的贴上我抄袭来的代码。。(呜啊!别打脸!!!)
哈哈哈哈哈,还是为又一次写上代码欢呼,oh yeah!
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define INF 200000000
int min(int a,int b)
{
return a>b?b:a;
}
int map[301][301],flow[301][301],pre[301],add[301],queue[1000001];
int main()
{
int n,m,i,j,k,l,s,e,c,begin,end,x,f;
while(scanf("%d%d",&n,&m)!=EOF)
{
f=0;
memset(map,0,sizeof(map));
memset(flow,0,sizeof(flow));
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&s,&e,&c);
map[s][e]+=c;
}
while(1)
{
memset(pre,0,sizeof(pre));
memset(add,0,sizeof(add));
add[1]=INF;
begin=0;end=1;
queue[0]=1;
while(end!=begin)
{
x=queue[begin];
begin++;
for(i=1;i<=m;i++)
{
if(add[i]==0&&map[x][i]>flow[x][i])
{
pre[i]=x;
queue[end]=i;
end++;
add[i]=min(add[x],map[x][i]-flow[x][i]);
}
}
}
if(add[m]==0)
break;
else
{
for(i=m;i!=1;i=pre[i])
{
flow[pre[i]][i]+=add[m];
flow[i][pre[i]]-=add[m];
}
f+=add[m];
}
}
printf("%d\n",f);
}
return 0;
}