Party --HOJ 11889

1、题目类型:图论、最大流、Edmonds_Karp算法。

2、解题思路:(1)根据建立图的连接矩阵,并记录被匹配男生的总数目cnt;(2)判断cnt与男生数目的大小,如果cnt小则表示不可能完成任务,直接 impossible;(3)由最小可能party数目开始遍历,每次女生的输出容量加加,直到Edmonds_Karp寻找最大流等于男生数目即找到了最佳答案,否则impossible。

3、注意事项:注意当cnt不可能满足时,不进入Edmonds_Karp,否则TLE。

4、实现方法:

#include<iostream>
using namespace std;
#define MAXN 180

int m,w,s,t,cnt,ans;
int map[MAXN][MAXN],r[MAXN][MAXN];
int pre[MAXN],d[MAXN];
bool vis[MAXN];

void Init()
{
int i,j,a,b;
cnt
=0;
memset(map,
0,sizeof(map));
memset(vis,
0,sizeof(vis));
cin
>>m>>w;
for(i=1;i<=m;i++)
map[
0][i]=1;
for(i=m+1;i<=w+m;i++)
{
cin
>>a;
for(j=0;j<a;j++)
{
cin
>>b;
b
++;
map[b][i]
=1;
if(!vis[b])
{
cnt
++;
vis[b]
=1;
}
}
}
}

//以下求最短路径增广
bool BFS(int s, int t, int n)
{
int front, rear, u, v;
int Q[MAXN * MAXN];
memset(pre,
-1, sizeof(pre));
front
= rear = 0;
Q[rear
++] = s;
d[s]
= 0;
while (front < rear)
{
u
= Q[front++];
for (v = 0; v < n; v++)
{
if (pre[v] == -1 && r[u][v] > 0)
{
pre[v]
= u;
d[u]
= d[v] + 1;
Q[rear
++] = v;
if(v == t) return true;
}
}
}
return false;
}

int Edmonds_Karp(int s, int t, int n)
{
int u, v, inc, maxflow = 0;
while (true)
{
//终点不在剩余网络中
if (!BFS(s, t, n)) break;
inc
= 10000000;
//以下求增广的流量
for (v = t; v != s; v = u)
{
u
= pre[v];
if(r[u][v] < inc) inc = r[u][v];
}
//以下重建剩余网络
for(v = t; v != s; v = u)
{
u
= pre[v];
r[u][v]
-= inc;
r[v][u]
+= inc;
}
//增加流量
maxflow += inc;
}
return maxflow;
}

void Solve()
{
int flag=0;
ans
=m/w;
s
=0;
t
=w+m+1;
for(int i=ans;i<=m;i++)
{
for(int j=m+1;j<=w+m;j++)
map[j][t]
=i;
memcpy(r,map,
sizeof(map));
if(Edmonds_Karp(s,t,t+1)==m)
{
cout
<<i<<endl;
flag
=1;
break;
}
}
if(!flag)
cout
<<"impossible"<<endl;
}

int main()
{
int T;
cin
>>T;
while(T--)
{
Init();
if(cnt<m)
cout
<<"impossible"<<endl;
else
Solve();
}
return 0;
}

 

posted @ 2010-09-23 08:38  勇泽  阅读(406)  评论(2编辑  收藏  举报