【网络流】HDU 3549 Flow Problem

Flow Problem

Problem Description

Network flow is a well-known difficult problem for ACMers. Given a graph, your task is to find out the maximum flow for the weighted directed graph.

Input

The first line of input contains an integer T, denoting the number of test cases.
For each test case, the first line contains two integers N and M, denoting the number of vertexes and edges in the graph. (2 <= N <= 15, 0 <= M <= 1000)
Next M lines, each line contains three integers X, Y and C, there is an edge from X to Y and the capacity of it is C. (1 <= X, Y <= N, 1 <= C <= 1000)

Output

For each test cases, you should output the maximum flow from source 1 to sink N.

Sample Input

 

2 3 2 1 2 1 2 3 1 3 3 1 2 1 2 3 1 1 3 1

Sample Output

 

Case 1: 1 Case 2: 2

题意:网络流,起点为i,有N个点,终点为N,求最大流。

网络流求最大流的典型例题,几乎就是模板。刚刚接触这类题,注释较详细。下面是利用队列广搜反复求增广路径的KM算法解决最大流问题。当然别的算法也有,过后介绍。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
#define INF 0x7f7f7f7f
using namespace std;

int flow[205][205]/*记录路径流*/, cap[205][205]/*路径的容量*/, p[205]/*父路径*/, c[205]/*残留路径*/;

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


int main()
{
    int N,M,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( maxflow, M );
        printf( "Case %d: %d\n", ++ca, maxflow );
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值