传送门: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;
}