POJ 1719 Shooting Contest 二分匹配

题意:给你r*c(行*列)的格子,每一列有2个白色格子,其余为黑色。需要找m个点,

找完之后,每一列只能选一个白色格子,每一行至少一个白色格子。如果找到,输出这m个点所在的行,从第一列开始输出,结果不唯一。

思路:每一行与列匹配,余下的列就随便找一个,如果行都没有匹配,则输出NO。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m;
int vis[1000+5];
struct node
{
	int oth;
	int v,next;
}e[2000+5],E[1000+5];
int head[1000+5],cnt;
int linker[1000+5];
void Init()
{
	memset(head,-1,sizeof(head));
	memset(linker,-1,sizeof(linker));
	cnt=0;
}
void add(int a,int b)
{
	e[cnt].v=b;
	e[cnt].next=head[a];
	head[a]=cnt++;
}
void Input()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d %d",&E[i].oth,&E[i].v);
		add(E[i].oth,i);
		add(E[i].v,i);
	}
}
int dfs(int u)
{
	for(int i=head[u];i+1;i=e[i].next)
	{
		int v=e[i].v;
		if(!vis[v])
		{
			vis[v]=1;
			if(linker[v]==-1||dfs(linker[v]))
			{
				linker[v]=u;
				return 1;
			}
		}
	}
	return 0;
}
void treatment()
{
	int res=0;
	for(int i=1;i<=n;i++)
	{
		if(head[i]==-1) continue;
		memset(vis,0,sizeof(vis));
		res+=dfs(i);
	}
	if(res!=n) printf("NO\n");
	else 
	{
		for(int i=1;i<=m;i++)
		{
			int ans;
			if(linker[i]==-1) ans=E[i].oth;
			else ans=linker[i];
			if(i==1) printf("%d",ans);
			else printf(" %d",ans);
		}
		printf("\n");
	}
} 
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		Init();
		Input();
		treatment();
	}
	return 0;
} 

你可能感兴趣的:(二分匹配)