傳送門: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;
}