【网络流】最大流模板1

杭电3549就是一道最经典的最大流问题,基本上就是套模板。输入两个数 点数M 路径数N,然后输入N行。每行有三个数x,y,z。分别代表头结点尾节点和路径长度。 网络流是个有向图。

下是最大流问题的KM算法,通过反复找增广路径来获得最大流量。

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define INF 0x7f7f7f7f
using namespace std;
int flow[205][205]/*记录路径流*/, cap[205][205]/*路径的容量*/, p[205]/*父路径*/, c[205]/*残留路径*/;
int maxflow;
int M;
void BFS()
{
    queue<int>q;
    maxflow=0;
    bool there=1;//初始化这里有增广路径
    memset( flow, 0, sizeof( flow ) );
    while(there)//找增广路径的循环,没有增广路径则跳出
    {
        memset( p, 0, sizeof( p ) );
        memset( c, 0, sizeof( c ) );
        c[1]= INF, p[1]=-1;
        q.push( 1 );
        while( !q.empty() )//广搜的循环
        {
            int pos= q.front();
            q.pop();
            for( int i=1; i<= M; ++i )
            {
                if( !c[i]&& flow[pos][i]< cap[pos][i] )  // 残留流量为0并且流入这点的路径中流量比容量小
                {
                    c[i]= min( c[pos], cap[pos][i]- flow[pos][i] );  // 选取当前管道残留容量和截止到上一次的路径残留容量之间的较小者,可以看作是一种更新
                    //即该增广路径的残留容量是有路径中残留容量最小的管道决定的
                    //每一次广搜都要把能使残留流量最小的流储存,在这里更新流会造成破坏,存入不是最优解
                    p[i]= pos;  // 记录父亲路径
                    q.push( i );
                }
            }
        }
        if( c[M]==0 )//没有残留路径到达N点,则跳出循环结束
            there=0;
        maxflow+= c[M];
        int pos= M;
        while(there&& pos!=1 )//从终点倒序更新路径流量,每次只更新
        {
            flow[ p[pos] ][ pos ]+= c[M];
            flow[ pos ][ p[pos] ]-= c[M];
            pos= p[ pos ];
        }
    }
}


int main()
{
    int N,maxflow, ca=0, T;
    scanf( "%d", &T );
    while( T-- )
    {
        scanf( "%d %d", &M, &N );
        memset( cap, 0, sizeof( cap ) );
        for( int i=1; i<= N; ++i )
        {
            int x, y, z;
            scanf( "%d %d %d", &x, &y, &z );
            cap[x][y]+= z;
        }
        BFS();
        printf( "Case %d: %d\n", ++ca, maxflow );
    }
    return 0;
}

/**
6 8
1 2 4
1 3 5
2 4 2
2 5 4
3 4 1
3 5 4
4 6 3
5 6 6
*/

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值