Jzoj2308 聚会

  Tzdin想组织一个圣诞晚会。N位女士和M位男士(M>=N)会被邀请参加这个聚会。在聚会的开始,Tzdin会派发一些写着某位男士信息的卡片给每位女士;每位女士都会收到若干张这种卡片。然后每位女士可以从她收到的卡片里挑选一位男士作为她的伴侣。我们可以认为经过Tzdin的引导,每位女士都一定可以挑选到一位男士作为他的伴侣,而每位男士最多成为1位女士的伴侣。Tzdin想知道的是,有哪些男士,无论女士们怎么选择,最终都一定会拥有伴侣。

著名的稳定婚姻问题

好了不瞎扯,我们来看看怎么用二分图来解决这个问题

我们先做一次最大匹配,让后看看对于每一个被匹配的男士,如果匹配他的女士不能被匹配到除该男士以外的人,那么答案+1,因为匹配总是是确定的,为n,这个条件很重要

匈牙利真是一个优美的算法,真的可以和Dijkstra媲美了

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<vector>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 1010
#define clear(t) memset(t,0,sizeof t)
using namespace std;
vector<int> G[N];
int n,m,f[N],g[N],vis[N];
bool match(int x){
	for(int v,i=0;i<G[x].size();++i)
		if(!vis[v=G[x][i]]){
			vis[v]=1;
			if(!f[v] || match(f[v])){ f[v]=x; return 1; }
		}
	return 0;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int x,y,i=1;i<=n;++i)
		for(scanf("%d",&x);x--;G[i].push_back(y)) scanf("%d",&y);
	for(int i=1;i<=n;++i) clear(vis),match(i); memcpy(g,f,sizeof f);
	for(int i=1;i<=m;++i)
		if(g[i]){
			clear(vis); vis[i]=1; 
			memcpy(f,g,sizeof g);
			if(!match(f[i])) printf("%d\n",i);
		}
}


posted @ 2018-01-20 20:23  扩展的灰(Extended_Ash)  阅读(132)  评论(0编辑  收藏  举报