又是被虐的一天呢~(AC是不可能的,这辈子不可能AC的。做题又不会做,就是打打暴力,才能维持骗骗分这样子。在机房里的感觉比回家的感觉好多了!里面个个都是大佬,个个都是死宅,我超喜欢在里面的!)
(↑以上是正经的分割线)
Description
有一颗n个点的树,刚开始每个点都没有颜色。
Alice和Bob会轮流对这棵树的一个点涂色,Alice涂白,Bob涂黑,Alice先手。
若最后存在一个白点,使得这个白点所有相邻点都为白色,则Alice胜,否则Bob胜。
请问是先手必胜还是后手必胜。
Input
第一行一个整数n。
接下来n-1行每行两个整数ai,bi,表示有一条边连接ai,bi。
Output
若先手必胜,输出"First"(不含引号),否则输出"Second"(不含引号)。
Sample Input
3
1 2
2 3
Sample Output
First
HINT
2<=n<=10^5
保证输入为一棵n个点的树
本题采用subtask。存在10%的数据满足n≤8。
Solution
贪心即可。考虑当前树上的叶子节点,若先手将其父亲节点染为白色,则后手定会将其儿子节点染为黑色,否则该儿子节点满足条件,先手胜利。若该父亲节点有两个或以上儿子节点,先手必胜。
每一轮涂色后,该两点对胜负无影响,直接从树上删去,继续贪心。最后判断根节点是否满足条件即可。
Code
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 using namespace std;
5 struct edge{
6 int to,next;
7 }e[200010];
8 int n,head[100010];
9 int dfs(int u,int fa){
10 int flag=0;
11 for(int i=head[u];~i;i=e[i].next){
12 int v=e[i].to;
13 if(v==fa)
14 continue;
15 flag+=dfs(v,u);
16 }
17 if(flag>=2){
18 puts("First");
19 exit(0);
20 }
21 return flag^1;
22 }
23 int main(){
24 memset(head,-1,sizeof(head));
25 scanf("%d",&n);
26 for(int i=1,cnt=-1;i<n;i++){
27 int u,v;
28 scanf("%d%d",&u,&v);
29 e[++cnt]=(edge){v,head[u]};
30 head[u]=cnt;
31 e[++cnt]=(edge){u,head[v]};
32 head[v]=cnt;
33 }
34 if(dfs(1,0))
35 puts("First");
36 else
37 puts("Second");
38 return 0;
39 }