题意:求有向图的最大流
解题思路:
- 参考USACO这篇阅读文献的伪代码(http://cerberus.delos.com:791/usacotext2?a=59NtETPig5G&S=flow)即可
- 要注意的是两点之间可能有多条边,将这些边的流量加起来,看作一条边即可
代码:
/*
ID: zc.rene1
LANG: C
PROG: ditch
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_N 200
#define MAX_M 200
int N, M, ceiling = 1;
int capacity[MAX_M + 1][MAX_M + 1];
int GetMin(int a, int b)
{
return a < b ? a : b;
}
int GetFlow(int source, int sink)
{
int prevnode[MAX_M + 1];
int flow[MAX_M + 1];
int visited[MAX_M + 1];
int total_flow = 0;
int i, max_flow, max_loc, curnode, nextnode;
if (source == sink)
{
return ceiling;
}
while (1)
{
for (i=1; i<=M; i++)
{
prevnode[i] = -1;
flow[i] = 0;
visited[i] = 0;
}
flow[source] = ceiling;
while (1)
{
max_flow = 0;
max_loc = -1;
for (i=1; i<=M; i++)
{
if (visited[i] == 0)
{
if (flow[i] > max_flow)
{
max_flow = flow[i];
max_loc = i;
}
}
}
if (max_loc == -1)
{
break;
}
if (max_loc == sink)
{
break;
}
visited[max_loc] = 1;
for (i=1; i<=M; i++)
{
if (capacity[max_loc][i] != 0)
{
if (flow[i] < GetMin(max_flow, capacity[max_loc][i]))
{
prevnode[i] = max_loc;
flow[i] = GetMin(max_flow, capacity[max_loc][i]);
}
}
}
}
if (max_loc == -1)
{
break;
}
total_flow += flow[sink];
curnode = sink;
while (curnode != source)
{
nextnode = prevnode[curnode];
capacity[nextnode][curnode] -= flow[sink];
capacity[curnode][nextnode] += flow[sink];
curnode = nextnode;
}
}
return total_flow;
}
int main(void)
{
FILE *fin, *fout;
int p1, p2, cap, i;
fin = fopen("ditch.in", "r");
fout = fopen("ditch.out", "w");
memset(capacity, 0, (MAX_M + 1) * (MAX_M + 1) * sizeof(int));
fscanf(fin, "%d %d", &N, &M);
for (i=0; i<N; i++)
{
fscanf(fin, "%d %d %d", &p1, &p2, &cap);
capacity[p1][p2] += cap;
if (p2 == M)
{
ceiling += cap;
}
}
fprintf(fout, "%d\n", GetFlow(1, M));
return 0;
}