Time limit per test: 2.0 seconds
Memory limit: 256 megabytes
oxx 和 xjj 终于上了船,船上的时光总是如此漫长,因此 oxx 决定与 xjj 一同玩一个无聊的游戏。
游戏规则很简单,首先由 xjj 随机画一棵树,随后两人轮流从树中选取一个度数不为 0 的结点 (度数为 0 则不与任何边相连) 将其与其相连的边删去,谁最终无法删去结点,则谁败。由于 xjj 画的树,因此 oxx 可以优先选择自己先手还是后手。
聪明的 oxx 看透了其中的套路,因此他知道他先手或者后手有必胜策略,若他先手有必胜策略则输出 First,否则输出 Second。
Input
第一行一个整数 n (2≤n≤20),表示结点个数。
接下去 n−1 行,每行两个整数 a,b (1≤a,b≤n,a≠b),表示 a 与 b 之间有边相连。
数据保证是一棵树。
Output
输出一行字符串,First 或 Second 表示 oxx 先手有必胜策略或者后手有必胜策略。
Examples
Input1
2
1 2
Output1
First
Input2
4
1 2
2 3
3 4
Output2
Second
题解: 可把本智障气坏了(哼)两眼一闭大力搜
已知当点数为1和点数为0时先手必败,dfs(status)表示status这个状态是否是先手必胜态,枚举当前删去哪个点,若其可以通过一步转化成先手必败,则返回值为0,否则为1,因为点只有20个,所以记忆化一下是OK的。
#include
#define LiangJiaJun main
#define INF 199912270000000LL
#define ll long long
using namespace std;
int n,cnt=0;
int mp[24][24],ru[24],cu[24];
bool vis[24];
int sg[1<<20];
int dfs(int x){
if(sg[x]!=-1)return sg[x];
sg[x]=0;
int temp[24][24],rt[24],ct[24];
bool td[24];
for(int i=1;i<=n;i++){
if(!vis[i])continue;
for(int a=1;a<=n;a++)rt[a]=ru[a];
for(int a=1;a<=n;a++)ct[a]=cu[a];
for(int a=1;a<=n;a++)td[a]=vis[a];
for(int a=1;a<=n;a++){
if(mp[i][a])--ru[a];
if(mp[a][i])--cu[a];
if(ru[a]+cu[a]==0||a==i)vis[a]=0;
}
int now=0;
for(int a=n;a>=1;a--){
now<<=1;
if(vis[a])now|=1;
}
if(!dfs(now)){
sg[x]=1;break;
}
for(int a=1;a<=n;a++)ru[a]=rt[a];
for(int a=1;a<=n;a++)cu[a]=ct[a];
for(int a=1;a<=n;a++)vis[a]=td[a];
}
return sg[x];
}
int w33ha(){
memset(mp,0,sizeof(mp));
memset(ru,0,sizeof(ru));
memset(cu,0,sizeof(cu));
for(int i=1;iint u,v;
scanf("%d%d",&u,&v);
mp[u][v]=1;
++cu[u];++ru[v];
}
int ans=0;
for(int i=0;i<(1<1;
for(int i=1;i<=n;i++)vis[i]=1;
sg[0]=0;sg[1]=0;
if(dfs((1<1))puts("First");
else puts("Second");
return 0;
}
int LiangJiaJun(){
while(scanf("%d",&n)!=EOF)w33ha();
return 0;
}