1. 程式人生 > 其它 >[AGC017D] Game on Tree

[AGC017D] Game on Tree

顯然是水部落格。

前言

關於萌新剛學SG函式而只會 \(O(n^2)\) 做法這件事。

題目

洛谷

AtCoder

講解

從易到難思考。

如果根節點只有一個兒子,這很好,先手砍掉這個點就能獲勝。

如果根節點有兩個兒子,那麼率先到一個兒子狀態的人獲勝。然後遞迴看這兩個兒子的遊戲狀態。

此時就已經可以用SG函式分析了,但顯然萌新不太會證明,只會感性理解每個點的SG值為其所有兒子SG值+1的異或和。

因此只需要簡單的dfs就可以完成這道題。

時間複雜度 \(O(n)\)

程式碼

//12252024832524
#include <bits/stdc++.h>
#define TT template<typename T>
using namespace std;

typedef long long LL;
const int MAXN = 100005;
int n;

LL Read()
{
	LL x = 0,f = 1; char c = getchar();
	while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

int head[MAXN],tot;
struct edge
{
	int v,nxt;
}e[MAXN<<1];
void Add_Edge(int x,int y)
{
	e[++tot] = edge{y,head[x]};
	head[x] = tot;
}
void Add_Double_Edge(int x,int y)
{
	Add_Edge(x,y);
	Add_Edge(y,x);
}

int dfs(int x,int fa)
{
	int ret = 0;
	for(int i = head[x]; i ;i = e[i].nxt) if(e[i].v ^ fa) ret ^= dfs(e[i].v,x)+1;
	return ret;
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n = Read();
	for(int i = 1;i < n;++ i) Add_Double_Edge(Read(),Read());
	printf(dfs(1,0) ? "Alice\n" : "Bob\n");
	return 0;
}