acdream 1403 Graph Game 二分匹配

8 篇文章 0 订阅
4 篇文章 0 订阅

传送门:acdream 1403

        给定一张二分图,现在有一场博弈,给一个点定一个标记,然后每次操作把标记移动到某个相邻的点上面,然后把原点以及所有相邻的边都剔除,无法移动的人判输。现在需要你判断所有点为起点时,先手必输还是必胜。

         

        战斗名族的题果然不一样,ASC做的时候就是想不到,就是简单的二分匹配,然后判断每个点剔除之后最大匹配是否会减少,若减少了则说明该点是二分匹配的关键点,剔除之后导致无法移动回原集团,即最终移动步数为奇数,因此先手胜,否则无论怎么动都能移动回来,即先手输

/******************************************************
 * File Name:   1403.cpp
 * Author:      kojimai
 * Creater Time:2014年10月03日 星期五 10时40分32秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define FFF 505
int linkx[FFF],linky[FFF],n1,n2;
vector<int> p[2][FFF];
bool ans1[FFF],ans2[FFF],visx[FFF],visy[FFF];
bool dfs(int x)
{
//	cout<<"x="<<x<<endl;
	for(int i = 0;i < p[0][x].size(); i++)
	{
		int v = p[0][x][i];
		if(!visy[v])
		{
//			cout<<" v="<<v<<" link="<<linky[v]<<endl;
			visy[v] = true;
			if(linky[v]==-1 || dfs(linky[v]))
			{
				linkx[x] = v;
				linky[v] = x;
				return true;
			}
		}
	}
	return false;
}
bool dfs2(int y)
{
	for(int i = 0;i < p[1][y].size();i++)
	{
		int v = p[1][y][i];
		if(!visx[v])
		{
			visx[v] = true;
			if(linkx[v] == -1 || dfs2(linkx[v]))
			{
				linkx[v] = y;
				linky[y] = v;
				return true;
			}
		}
	}
	return false;
}
void out()
{
	for(int i =1;i <= 3;i++)
	{
		cout<<"i="<<i<<" linkx[i]="<<linkx[i]<<endl;
		cout<<"i="<<i<<" linky[i]="<<linky[i]<<endl;
	}
}
int main()
{
	int m,x,y;
	scanf("%d%d%d",&n1,&n2,&m);
	for(int i = 0;i < m; i++)
	{
		scanf("%d%d",&x,&y);
		p[0][x].push_back(y);
		p[1][y].push_back(x);
	}
	memset(linkx,-1,sizeof(linkx));
	memset(linky,-1,sizeof(linky));
	for(int i = 1;i <= n1; i++)
	{
		if(linkx[i] == -1)
		{
			memset(visy,false,sizeof(visy));
			dfs(i);
		}
	}//先找出可能的最大匹配
	//out();
	memset(ans1,false,sizeof(ans1));
	memset(ans2,false,sizeof(ans2));
	for(int i = 1;i <= n1; i++)//起点为左边集团的点时,先剔除该点然后看最大匹配是否减少
	{
		if(linkx[i] == -1)
			continue;
		else{
			memset(visx,false,sizeof(visx));
			visx[i] = true;
			if(!dfs2(linkx[i]))
			{
				ans1[i] = true;//若最大匹配减少了,即剔除该点之后无法构成新的最大匹配
			}
			else
				linkx[i] = -1;//若能构成最大匹配则要把原来的边剔除
		}
	}
	//out();
	for(int i = 1;i <= n2; i++)//起点为右边集团的点时,同上
	{
		if(linky[i] == -1)
			continue;
		else  {
			memset(visy,false,sizeof(visy));
			visy[i] = true;
			if(!dfs(linky[i]))
				ans2[i] = true;
			else
				linky[i] = -1;
		}
	}
	//out();
	for(int i = 1;i <= n1;i++)
	{
		if(ans1[i])
			cout<<'N';
		else
			cout<<'P';
	}
	cout<<endl;
	for(int i = 1;i <= n2;i++)
	{
		if(ans2[i])
			cout<<'N';
		else
			cout<<'P';
	}
	cout<<endl;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值