题意:
给出一棵有N个点的树。开始时,所有点都没被染色。两个人在这棵树上玩游戏。他们轮流操作:选择一个点,如果是先手操作,就把点涂成白色,否则涂成黑色。当所有点都被染色后,对于每一个与黑色点相邻的白色点,同时染成黑色。如果还有白点,先手胜,否则后手胜。两个人都采取最优策略,求出胜利者。
题解:
我们证明一下如果后手胜当且仅当这棵树是一个完全匹配。
先证充分性:先手选择一个点,后手选择该点的匹配即可。
再证必要性:如果不是完全匹配,那么一定有一个没匹配到的点,就让它为根。我们要找到父亲只有一个儿子的叶节点。如果没有,显然不是完全匹配,先手可以直接选择父亲,那么后手就GG了。然后先手选父亲,后手选儿子,否则先手一定会被后手染色。最后一定剩下一个点,让先手操作即可。
我也不知道我有没有把充分和必要写反QAQ
代码:
#include<cstdio>
#include<algorithm>
#define maxn 100005
using namespace std;
int n,ma[maxn];
struct node { int v; node *nxt; } edge[maxn*2],*head[maxn],*ncnt;
void addedge(int u,int v)
{
ncnt++;
ncnt->v=v,ncnt->nxt=head[u];
head[u]=ncnt;
}
void dfs(int u,int fa)
{
for(node *p=head[u];p;p=p->nxt)
{
int v=p->v;
if(v==fa) continue;
dfs(v,u);
if(!ma[v])
{
if(ma[u]) { printf("First\n"); exit(0); }
ma[u]=v,ma[v]=u;
}
}
}
int main()
{
ncnt=&edge[0];
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v); addedge(v,u);
}
dfs(1,0);
printf("%s\n",ma[1]?"Second":"First");
}