poj 1486

可以直接模拟这个过程,可知如果当前有点仅属于某个幻灯片,那么便可确定此点和此幻灯片的匹配关系,反之如果有幻灯片只包括某个点,也可确定此幻灯片和此点的匹配关系,如果没有这两种情况的话,剩下的就不能确定了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#define LL long long
#define myabs(x) ((x)>0?(x):(-(x)))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=500+10;
struct node
{
	int xmin,xmax,ymin,ymax;
};
node slide[maxn];
int re[maxn],vis2[maxn];
int g1[maxn][maxn],g2[maxn][maxn];
int n,m;
void solve()
{
	memset(re,0,sizeof(re));
	int flag=1;
	int i,j,k;
	while(flag)
	{
		flag=0;
		for(i=1;i<=n;i++)
		{
			if(g1[i][0]==1)
			{
				flag=1;
				for(j=1;j<=n;j++) if(g1[i][j]) break;
				re[i]=j;
				g2[j][0]=0;//相当于vis赋为1
				for(k=1;k<=n;k++)
				{
					if(g1[k][j])
					{
						g1[k][0]--;
						g1[k][j]=0;
					}
				}
			}
		}
		for(i=1;i<=n;i++)
		{
			if(g2[i][0]==1)
			{
				flag=1;
				for(j=1;j<=n;j++) if(g2[i][j]) break;
				re[j]=i;
				g1[j][0]=0;
				for(k=1;k<=n;k++)
				{
					if(g2[k][j]) 
					{
						g2[k][j]=0;
						g2[k][0]--;
					}
				}
			}
		}
	}
}
int main()
{
	int cas=0;
	while(~scanf("%d",&n)&&n)
	{
		int i,j,u,v;
		for(i=1;i<=n;i++)
			scanf("%d%d%d%d",&slide[i].xmin,&slide[i].xmax,&slide[i].ymin,&slide[i].ymax);
		int x,y,flag=1;
		memset(g1,0,sizeof(g1));
		memset(g2,0,sizeof(g2));
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&x,&y);
			for(j=1;j<=n;j++)
			{
				if(x>slide[j].xmin&&x<slide[j].xmax&&y>slide[j].ymin&&y<slide[j].ymax)
				{
					g1[j][i]=g2[i][j]=1;
					g1[j][0]++;
					g2[i][0]++;
				}
			}
		}
		printf("Heap %d\n",++cas);
		solve();
		for(i=1;i<=n;i++)
		{
			if(re[i])
			{
				if(flag)
				{
					flag=0;
					printf("(%c,%d)",i-1+'A',re[i]);
				}
				else printf(" (%c,%d)",i-1+'A',re[i]);
			}
		}
		if(flag) printf("none");
		printf("\n\n");
	}
	return 0;
}
也可用二分图的匹配来做。首先求出一个最大匹配,然后去看每个点是否必须和他匹配的那个点匹配,就是删除两点的边,看是否还能构成匹配数为n的最大匹配。这里不需要从头再算一次增广路算法。因为删去此边之后,对其他点的匹配没有影响。增广路算法对点的增广不分先后 ,那么可以先去增广匹配其他的点,显然,其他的点肯定能增广匹配,而且其增广匹配的一种结果已经得出,不就是之前第一次求出的匹配关系吗,这些关系没有变,所有就直接增广当前删去的边所对应的点就可以了。但是增广的过程中就不要修改left值了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#define LL long long
#define myabs(x) ((x)>0?(x):(-(x)))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=500+10;
struct node
{
	int xmin,xmax,ymin,ymax;
};
node slide[maxn];
int con[maxn][maxn];
int g[maxn][maxn];
int leftp[maxn],vis[maxn];
int n,m;
int omg;
int dfs(int u)
{
	int i;
	for(i=1;i<=n;i++)
	{
		if(g[u][i]&&!vis[i])
		{
			vis[i]=1;
			if(!leftp[i]||dfs(leftp[i]))
			{
				if(omg)leftp[i]=u;/////////////////注意omg的使用
				return 1;
			}
		}
	}
	return 0;
}
int solve()
{
	omg=1;/////////////////////////////////
	int u,v;
	int sum=0;
	for(u=1;u<=n;u++)
	{
		memset(vis,0,sizeof(vis));
		if(dfs(u))
			sum++;
	}
	return sum;
}
int main()
{
	int cas=0;
	while(~scanf("%d",&n)&&n)
	{
		int i,j,u,v;
		memset(g,0,sizeof(g));
		memset(leftp,0,sizeof(leftp));
		memset(con,0,sizeof(con));
		for(i=1;i<=n;i++)
			scanf("%d%d%d%d",&slide[i].xmin,&slide[i].xmax,&slide[i].ymin,&slide[i].ymax);
		int x,y,flag=1;
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&x,&y);
			for(j=1;j<=n;j++)
				if(x>=slide[j].xmin&&x<=slide[j].xmax&&y>=slide[j].ymin&&y<=slide[j].ymax)
					g[i][j]=1;                           
		}
		printf("Heap %d\n",++cas);
		solve();
		int tem;
		omg=0;
		for(i=1;i<=n;i++)
		{
			tem=leftp[i];
			leftp[i]=0;
			g[tem][i]=0;
			memset(vis,0,sizeof(vis));
			if(!dfs(tem))
			{
				if(flag)
				{
					flag=0;
					printf("(%c,%d)",i-1+'A',tem);
				}
				else printf(" (%c,%d)",i-1+'A',tem);
			}
			leftp[i]=tem;
			g[tem][i]=1;
		}
		if(flag) printf("none");
		printf("\n\n");
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值