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
input
2 1 2
output
First
input
4 1 2 2 3 3 4
output
Second
题意:给你n颗树,两个人玩游戏,每次一个人选一颗度不为0的点,删除所有相连的边,若一个人无法选择,则输,问是先手必赢还是后手必赢。
题解:状压删除的情况,根据SG函数判断当前状态。
AC代码:
转载自: http://blog.csdn.net/acterminate/article/details/79323397
- #include<stdio.h>
- #include<vector>
- using namespace std;
- int dp[(1<<20)+5];
- vector<int>vt[25];
- int du[25],hadu[25];
- int main()
- {
- int n;
- scanf("%d",&n);
- for(int i=0;i<n-1;i++)
- {
- int u,v;
- scanf("%d%d",&u,&v);
- vt[u].push_back(v);
- vt[v].push_back(u);
- hadu[u]++;hadu[v]++;
- }
- for(int state=(1<<n)-1;state>=0;state--)
- {
- for(int i=0;i<n;i++)
- if((state&(1<<i)))
- {
- int flag=0;
- for(int j=0;j<vt[i+1].size();j++)
- {
- int to=vt[i+1][j];
- if(!((1<<(to-1))&state))
- flag=1;
- }
- if(flag)dp[state^(1<<i)]|=dp[state]^1;
- }
- }
- if(dp[0])printf("First\n");
- else printf("Second\n");
- }