pku 1486 Sorting Slides

题意:给定N张幻灯片的maxx,minx,maxy,miny,和N个点的位置,表示幻灯片的编号,编号写在幻灯片上,问幻灯片与编号形成的最大匹配能否确定唯一的匹配,输出已确定的唯一匹配;

分析:若编号与幻灯片满足 minx<x<maxx, miny<y<maxy,则形成一个可能的匹配,求出最大匹配(肯定是完美匹配的)之后,再依次判定该匹配边是否为必须边

判定方法:先将该匹配边删除,判定从该点出发是否存在增广路径,若存在,则不是必须边,反之,为必须边;

#include<iostream>
using namespace std;
bool mat[26][26],vis[26];
int mx[26],my[26],n;
struct slide
{
	int xmin,xmax,ymin,ymax;
}s[26];
struct point
{
	int x ,y;
}p[26];
int path(int s)
{
	for(int i=0;i<n;i++)
		if(mat[s][i]&&!vis[i])
		{
			vis[i]=1;
			if(my[i]==-1||path(my[i]))
			{
				my[i]=s;
				mx[s]=i;
				return 1;
			}
		}
	return 0;
}
bool judge(int i,int j)
{
	if(p[j].x<s[i].xmax&&p[j].x>s[i].xmin&&p[j].y<s[i].ymax&&p[j].y>s[i].ymin)
		return true;
	return false;
}
int main()
{
	int cas=0;
	while(scanf("%d",&n)==1&&n)
	{
		for(int i=0;i<n;i++)
			scanf("%d %d %d %d",&s[i].xmin,&s[i].xmax ,&s[i].ymin,&s[i].ymax);
		for(int i=0;i<n;i++)
			scanf("%d %d",&p[i].x,&p[i].y);
		memset(mat,0,sizeof(mat));
		memset(my,-1,sizeof(my));
		memset(mx,-1,sizeof(mx));
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
			{
				if(judge(i,j))
					mat[i][j]=1;
			}
		for(int i=0;i<n;i++)
			if(mx[i]==-1)
			{
				memset(vis,0,sizeof(vis));
				path(i);
			}
		printf("Heap %d\n",++cas);
		int flag=1;
		for(int i=0;i<n;i++)
		{
			int y=mx[i];
			mx[i]=-1;
			my[y]=-1;
			mat[i][y]=0;
			memset(vis,0,sizeof(vis));
			if(!path(i))
			{
				if(flag)
				{printf("(%c,%d)",i+'A',y+1);flag=0;}
				else 	
				printf(" (%c,%d)",i+'A',y+1);
				mx[i]=y;
				my[y]=i;
			}
			mat[i][y]=1;
		}
		if(!flag) printf("\n\n");
		else printf("none\n\n");
	}
	return 0;
}

转载于:https://www.cnblogs.com/nanke/archive/2011/09/02/2163342.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值