#include <bits/stdc++.h>
const int INF = 0x7f7f7f7f;
using namespace std;
int flow[205][205], cap[205][205], p[205], c[205]; // f用来记录单前节点流,p用来记录父路径
void BFS( int&maxflow, int N )
{
queue<int>q;
maxflow = 0;
bool finish = false;
memset( flow, 0, sizeof( flow ) );
while ( !finish )
{
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] ) // 如果该条边没有达到饱和或者形成回流
{
c[i] = min( c[pos], cap[pos][i] - flow[pos][i] ); // 选取当前管道残留容量和截止到上一次的路径残留容量之间的较小者,可以看作是一种更新
// 即该增广路径的残留容量是有路径中残留容量最小的管道决定的
p[i] = pos; // 记录父亲路径
q.push( i );
}
}
}
if ( c[N] == 0 )
{
finish = true;
}
maxflow += c[N];
int pos = N;
while ( !finish && pos != 1 )
{
flow[ p[pos] ][ pos ] += c[N];
flow[ pos ][ p[pos] ] -= c[N];
pos = p[ pos ];
}
}
}
int main(int argc, char const *argv[])
{
int N, M, 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( maxflow, M );
printf( "Case %d: %d\n", ++ca, maxflow );
}
return 0;
}
网络流模板题