hdu 3549

题目概述

有N个点,编号1到N,M条边,求从1到N的最大流

时限

5000ms/5000ms

输入

第一行整数times,其后times组数据,每组数据第一行整数N,M,其后M行,每行三个整数a,b,c,代表a到b的边,残量为c

限制

2<=N<=15;0<=M<=1000

输出

每行一个字符串
Case A: B
A为数据序数,从1开始,B为所求最大流

样例输入

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

样例输出

Case 1: 1
Case 2: 2

讨论

图论,网络流,最大流,Isap+gap优化,没什么可说的,背模版就可以

题解状态

109MS,1736K,1563 B,C++

题解代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 20
#define memset0(a) memset(a,0,sizeof(a))

int N, M, S, T;//点总数 边总数 源点 汇点
int R[MAXN][MAXN], dis[MAXN], from[MAXN], gap[MAXN];//残量矩阵 层次 父节点 每个层次的节点数
queue<int>q;
int fun()
{
    for (int p = 0; p < M; p++) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);//input
        R[a][b] += c;//防止重边
    }
    S = 1, T = N;
    for (int p = 1; p <= N; p++)//下面是bfs划定层次
        dis[p] = N;
    gap[dis[T] = 0]++;
    q.push(T);
    while (!q.empty()) {
        int a = q.front();
        q.pop();
        for (int p = 1; p <= N; p++)
            if (dis[p] == N&&R[p][a]) {
                q.push(p);
                gap[dis[p] = dis[a] + 1]++;
            }
    }
    int most = 0, p = S, flow = INF;//下面是isap主体
    while (dis[S] < N) {
        int i;
        for (i = 1; i <= N && (!R[p][i] || dis[p] != dis[i] + 1); i++);
        if (i != N + 1) {
            from[i] = p;
            flow = min(flow, R[p][i]);
            p = i;
            if (p == T) {
                while (p != S) {
                    i = from[p];
                    R[i][p] -= flow;
                    R[p][i] += flow;
                    p = i;
                }
                most += flow;
                flow = INF;
            }
        }
        else {
            if (!--gap[dis[p]])
                break;
            dis[p] = N;
            for (int i = 1; i <= N; i++)
                if (R[p][i] && dis[p] > dis[i] + 1)
                    dis[p] = dis[i] + 1;
            gap[dis[p]]++;
            if (p != S)
                p = from[p];
        }
    }
    return most;
}
int main(void)
{
    //freopen("vs_cin.txt", "r", stdin);
    //freopen("vs_cout.txt", "w", stdout);

    int times;
    scanf("%d", &times);//input
    for (int p = 1; p <= times; p++) {
        scanf("%d%d", &N, &M);//input
        printf("Case %d: %d\n", p, fun());//output
        memset0(R);
        memset0(gap);
    }
}

EOF

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值