POJ_1273_Drainage Ditches(USACO 93)_最大流

13 篇文章 0 订阅
9 篇文章 0 订阅

此题是最大流的裸题,适合网络流初学者练习。
Edmonds_Karp 增广路径算法运行过程:
如果能找到新的增广路径则:
用广度优先搜索,不断地找边最少的增广路径,同时记录每个点的前驱;
之后求出本次增广路径的流量大小(即为路径中最短的边的容量);
然后要给路径中的边都减去本次的流量,并将每两个点之间反向加上一条等于流量的边。

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=203;
const int inf =214748364;
int n,m,s=1,t;
int E[N][N],pre[N];//存边、记录前驱结点
bool vd[N];//记录BFS中的点是否已访问
int EK()
{
    deque <int>q;//双向队列
    bool FindPath=false;//记录是否可以找到一条从源点到汇点的路径
    memset (vd,false,sizeof(vd));
    memset (pre,0,sizeof(pre));
    q.push_back(s);
    pre[s]=0;//源点前驱为零
    vd[s]=true;
    while (q.size())//BFS搜索
    {
        int u=q.front();
        q.pop_front();
        for (int i=1;i<=m;i++)
        {
            if (E[u][i]>0&&vd[i]==false)
            {
                pre[i]=u;
                vd[i]=true;
                if (i==m)
                {
                    FindPath=true;
                    q.clear();
                    break;
                }
                else
                    q.push_back(i);
            }
        }
    }
    if (!FindPath)//没有增广路径了就结束
        return 0;
    int MinFlow=inf,v=m;
    while (pre[v])//计算出本次增广路径流量大小(即为路径中最小边流量)
    {
        MinFlow=min(MinFlow,E[pre[v]][v]);
        v=pre[v];
    }
    for (int i=m;i!=s;i=pre[i])
    {
        E[pre[i]][i]-=MinFlow;//从汇点到源点将走过的边都减去本次增广路径的流量
        E[i][pre[i]]+=MinFlow;//再反向加上本次增广路径的流量
    }
    return MinFlow;
}


int main()
{
    while (scanf ("%d%d",&n,&m)!=EOF)// !=EOF一定要写,不然超时
    {
        t=m;
        memset (E,0,sizeof(E));
        for (int i=1;i<=n;i++)
        {
            int a,b,c;
            scanf ("%d%d%d",&a,&b,&c);
            E[a][b]+=c;//注意两节点之间有可能出现多条水渠
        }
        int sum=0,aug;
        while (aug=EK())//若函数返回值为零,则跳出循环
            sum+=aug;
        printf ("%d\n",sum);
    }
    return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值