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;
}