题目概述
有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", ×);//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