[洛谷P2071] 座位安排

题目链接:###

座位安排

题目分析:###

二分图,人为左部点,座位为右部点,由于每个座位可以坐两个人,所以把每个座位拆成两个点\(i\)\(i+n\),如果一个人想去这个座位则向这两个点连边,跑匈牙利即可。

代码:###

#include<bits/stdc++.h>
#define N (100000+5)
using namespace std;
inline int read(){
	int cnt=0,f=1;char c;
	c=getchar();
	while(!isdigit(c)){
		if(c=='-')f=-f;
		c=getchar();
	}
	while(isdigit(c)){
		cnt=cnt*10+c-'0';
		c=getchar();
	}
	return cnt*f;
}
int n,match[N],x,y,nxt[N],first[N],to[N],tot,ans,res;
bool vis[N];

void add(int x,int y){
	nxt[++tot]=first[x];
	first[x]=tot;
	to[tot]=y;
}

int find(int u){
	for(register int i=first[u];i;i=nxt[i]) {
		int v=to[i];
		if(vis[v]) continue;
		else {
			vis[v]=1;
			if(match[v]==-1||find(match[v])){
				match[v]=u;
				return 1;
			}
		}
	}
	return 0;
}

int hungary(){
	for(register int i=1;i<=2*n;i++) match[i]=-1;

	for(register int i=1;i<=2*n;i++) {
		for(register int j=1;j<=2*n;j++) vis[j]=0;
		ans+=find(i);
	}
	return ans;
}

int main(){
	n=read();
	for(register int i=1;i<=2*n;i++){
		x=read();y=read();
		add(i,x);add(i,x+n);
		add(i,y);add(i,y+n);
	}
	int res=hungary();
	printf("%d",res);
	return 0;
}

posted @ 2019-01-27 16:55  kma_093  阅读(192)  评论(0编辑  收藏  举报