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

 

转载于:https://www.cnblogs.com/yongze103/archive/2010/09/23/1833247.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值