首页 > 其他 > 详细

YCH的模拟赛 T4

时间:2020-07-08 15:15:39      阅读:44      评论:0      收藏:0      [点我收藏+]

技术分享图片

黑白染色,二分图

技术分享图片

所有在最大匹配里面的点是必胜点?

不是,比如右边第三个点

那么在最大匹配里面有一些点是必胜点

结论是:必胜点一定在所有的最大匹配里面

证明:

如果小葱沿着匹配边走到了一个匹配点,分两种情况

如果大葱一直走匹配点,大葱必败

如果大葱走不在最大匹配里面的点,意味着小葱选择的点不是唯一的最大匹配点

所以选择所有的最大匹配点的公共点一定必胜

技术分享图片

下面证选择不在最大匹配的点一定必败

则小葱走到的点一定是匹配点,这个时候一定是大葱必胜

技术分享图片

怎么判断一个点是否一定在二分图最大匹配里面?

如果把每个点删掉在跑,显然会炸

在匈牙利匹配的时候让一个点匹配的点再找一个匹配点,如果对应的点不能找到另一个匹配,那么这个点就一定在最大匹配里面

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

const int maxn=510;
const int maxp=maxn*maxn;

int n,m,k,en,id[maxn][maxn],result[maxp],bx[5]={0,1,-1,0,0},by[5]={0,0,0,1,-1};

bool block[maxn][maxn],use[maxp];

struct edge
{
	int e;
	edge *next;
}*v[maxp],ed[maxp*4];

void add_edge(int s,int e)
{
	en++;
	ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;
}

bool dfs(int p)
{
	for (edge *e=v[p];e;e=e->next)
		if (!use[e->e])
		{
			use[e->e]=true;
			if (!result[e->e] || dfs(result[e->e]))
			{
				result[e->e]=p;
				result[p]=e->e;
				return true;
			}
		}
	return false;
}

bool dfs2(int p)
{
	for (edge *e=v[p];e;e=e->next)
		if (!use[e->e])
		{
			use[e->e]=true;
			if (!result[e->e] || dfs2(result[e->e])) return true;
		}
	return false;
}

int main()
{
	scanf("%d%d%d",&n,&m,&k);
	if (k==0)
	{
		if (n*m%2==1) printf("%d\n",n*m/2);
		else printf("%d\n",n*m);
		return 0;
	}
	for (int a=1;a<=k;a++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		block[x][y]=true;
	}
	int cnt=0;
	for (int a=1;a<=n;a++)
		for (int b=1;b<=m;b++)
			if (!block[a][b]) id[a][b]=++cnt;
	for (int a=1;a<=n;a++)
		for (int b=1;b<=m;b++)
			if (!block[a][b])
				for (int c=1;c<=4;c++)
				{
					int x=a+bx[c];
					int y=b+by[c];
					if (!block[x][y] && x<=n && x>=1 && y<=m && y>=1) add_edge(id[a][b],id[x][y]);
				}

	int ans=0;
	for (int a=1;a<=n;a++)
		for (int b=1;b<=m;b++)
			if ((a+b)&1)
			{
				if (block[a][b]) continue;
				memset(use,false,sizeof(use));
				if (dfs(id[a][b])) ans++;
			}
	for (int a=1;a<=cnt;a++)
		result[result[a]]=a;
	int res=0;
	for (int a=1;a<=cnt;a++)
		if (result[a])
		{
			memset(use,false,sizeof(use));
			use[a]=true;
			result[result[a]]=0;
			if (!dfs2(result[a])) res++;
			result[result[a]]=a;
		}
	printf("%d\n",res);

	return 0;
}

YCH的模拟赛 T4

原文:https://www.cnblogs.com/lcezych/p/13266883.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!