您的位置:首页 > 理论基础 > 计算机网络

UVa10779 Collectors' Problem( 网络流,建图)

2013-02-03 15:32 323 查看
这是一道建图的题,只要能想清楚怎么建图,就没有问题

建图:Bob和所有粘贴相连,边的容量是他所拥有粘贴的个数;

            其他人和他们所拥有的粘贴相连,边容量为手中物品个数减1,因为他们要保留一个

            其他人没有的粘贴,从粘贴连到这个人,容量为1,他只能接受一个这种粘贴

            每种粘贴和汇点相连,容量为1

代码如下:#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

const int inf = 99999999;
const int Maxn = 40;
int S, E, T, n, m;
int map[Maxn][Maxn], flow[Maxn][Maxn], a[Maxn], p[Maxn];

void buildMap() {
int ki, t;
for ( int i = 1; i <= n; ++i ) {
scanf("%d", &ki);
for ( int j = 0; j < ki; ++j ) {
scanf("%d", &t);
t += n;
map[i][t]++;
}
if ( i > 1 ) for ( int j = n + 1; j <= n + m; ++j )
if ( map[i][j] ) map[i][j]--;
else if ( map[i][j] == 0 ) map[j][i]++;
}
for ( int i = n + 1; i <= n + m; ++i ) map[i][E]++; //将表示物品的点和汇点相连,容量为1
}
int maxFlow() {
queue < int > q; int f = 0;
memset( flow, 0, sizeof(flow) );
while(1) {
memset( a, 0, sizeof(a) );
a[S] = inf;
q.push( S );
while( !q.empty() ) {
int u = q.front(); q.pop();
for( int v = 1; v <= m + n + 1; ++v ) {
if ( !a[v] && map[u][v] > flow[u][v] ) {
p[v] = u; q.push(v);
a[v] = min(a[u], map[u][v] - flow[u][v]);
}
}
}
if ( a[E] == 0 ) break;
for ( int u = E; u != S; u = p[u] ) {
flow[p[u]][u] += a[E];
flow[u][p[u]] -= a[E];
}
f += a[E];
}
return f;
}

int main()
{
int icase = 1;
while ( scanf("%d", &T) != EOF ) {
while ( T-- ) {
scanf("%d%d", &n, &m);
memset( map, 0, sizeof(map) );
S = 1, E = m + n + 1;
buildMap();
printf("Case #%d: %d\n", icase++, maxFlow());
}
}
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: