hdu1532 最大流 EK算法

一开始怎么也看不懂网络流,完全不明白那算法是怎么样的,直接导致我许多天没写代码了。。。今天终于上手了,\欢呼\撒花\。。。

准确来说,今天有了一点思路(虽然最后还是照着别人的代码敲了一遍,囧。。。)

这是简单的最大流问题,需要考虑的是有多重边需要注意,所以我们的做法是在原基础上加上重边上的容量。

最大流,我们用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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值