zoukankan      html  css  js  c++  java
  • HDU1532 网络流:最大流之福德福克森算法

    问题描述:约翰是个农民,每次下雨的时候他的庄家总是会被淹没,这就意味着当庄家被水淹后需要很长时间才能重新生长出来,因此,约翰已经建立了一系列排水管道为了使他的庄家尽可能被淹没的最少,也就是说管道的排水量必须很大.作为一名工程师,约翰可以计算出管道网能排水的最大能力.

    Input:输入包含多组用例,每组用例第一行是两个数N,M,N表示一共有N个管道,M表示一共有M个点,接下来N行每行输入三个数字a,b,c表示,a管道口到b管道口最大排水能力为c.

    Output:对每一组用例,输出排水量的最大值

    Sample Input:

    5 4
    1 2 40
    1 4 20
    2 4 20
    2 3 30
    3 4 10

    Sample Output:

    50

    这里我采用的是Fold-Fulkerson算法。

    //这里的起点默认为1,终点为节点数M
    
    #include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<string.h>
    #define maxint 999999999
    using namespace std;
    int rest[500][500];//二位数组rest绘制有向图
    int pre[500];//保存每次需找的增广路径的前驱
    int Min;//写法原因Min需定义为全局变量
    bool bfs(int M)//增广路径的搜索
    {
        queue<int>que;
        bool vis[500];//常规搜索都有的标记数组vis;
        memset(vis,0,sizeof(vis));
        memset(pre,-1,sizeof(pre));//前驱数组初始化
        que.push(1);
        vis[1]=1;
        while(!que.empty())
        {
            int s=que.front();
            que.pop();
            if(s==M)
            {
                return true;
            }
    
            for(int i=1;i<=M;i++)
            {
                if(rest[s][i]&&vis[i]==0)//rest[s][t]不为0说明选择的这条路径中从s点到达i点的通道还未被充满,说明当前存在增广路径
                {
                    pre[i]=s;//前驱数组更新
              vis[i]=1;
                    que.push(i);
                }
            }
        }
        return false;//若不存在增广路径则返回false说明找不到
    }
    
    void update(int M)//对每次所选的路径可增加流量更新,返回并加到总流量数sum中
    {
        if(M==1)//从后往前找起,知道找到起点为止
            return;
        int s=pre[M];
        Min=min(Min,rest[s][M]);
        update(s);//回溯更新
        rest[s][M]-=Min;//正反路径进行更新的区别
        rest[M][s]+=Min;
    }
    
    int main()
    {
        int a,b,c;
        int N,M;
        while(scanf("%d%d",&N,&M)!=EOF)
        {
            memset(rest,0,sizeof(rest));
            for(int i=1;i<=N;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                rest[a][b]+=c;//想清楚为什么是+不是=
            }
            int sum=0;
            while(bfs(M))
            {
                Min=maxint;//由于可能有多次路径选择所以需要在while内对全局变量Min进行初始化
                update(M);
                sum+=Min;
            }
            printf("%d
    ",sum);//输出到达终点可达到的最大流量
        }return 0;
    }
  • 相关阅读:
    使用WCF实现消息推送
    T31P电子秤数据读取
    持续性任务代码的一些测试
    XP+Android手机DIY家庭视频点播系统-历时3周全力打造吊丝的幸福生活
    Android 上传文件到XP
    Android ListView的一个坑,你可掉进去过?
    无脑无负担网站架构-- Application Request Route的一些应用
    Android 一些注意
    懒人的ERP开发框架--2B&苦B程序员专用
    PHP Token(令牌)设计应用
  • 原文地址:https://www.cnblogs.com/ziranduhuo/p/5929417.html
Copyright © 2011-2022 走看看