4730: Alice和Bob又在玩游戏
Time Limit: 40 Sec Memory Limit: 1024 MBSubmit: 116 Solved: 52
[ Submit][ Status][ Discuss]
Description
Alice和Bob在玩游戏。有n个节点,m条边(0<=m<=n-1),构成若干棵有根树,每棵树的根节点是该连通块内编号最
小的点。Alice和Bob轮流操作,每回合选择一个没有被删除的节点x,将x及其所有祖先全部删除,不能操作的人输
。注:树的形态是在一开始就确定好的,删除节点不会影响剩余节点父亲和儿子的关系。比如:1-3-2 这样一条链
,1号点是根节点,删除1号点之后,3号点还是2号点的父节点。问有没有先手必胜策略。n<=10^5。
Input
Output
Sample Input
4
2 1
1 2
3 2
1 2
1 3
2 0
3 1
1 2
2 1
1 2
3 2
1 2
1 3
2 0
3 1
1 2
Sample Output
Alice
Alice
Bob
Alice
Alice
Bob
Alice
HINT
Source
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1E5 + 10;
const int T = 20;
const int N = 15;
int Case,n,m,cnt,Ans,rt[maxn],ch[maxn*T*N][2],Mark[maxn*T*N],L[maxn*T*N],sg[maxn],sum[maxn];
bool All[maxn*T*N],vis[maxn];
vector <int> v[maxn];
void Clear()
{
for (int i = 1; i <= n; i++)
v[i].clear(),sum[i] = rt[i] = vis[i] = 0;
for (int i = 1; i <= cnt; i++)
ch[i][0] = ch[i][1] = Mark[i] = All[i] = 0;
cnt = Ans = 0;
}
void pushdown(int o)
{
if (!Mark[o]) return;
if (Mark[o] & (1 << L[o])) swap(ch[o][0],ch[o][1]);
for (int i = 0; i < 2; i++)
if (ch[o][i]) Mark[ch[o][i]] ^= Mark[o];
Mark[o] = 0;
}
int Merge(int o1,int o2)
{
if (!o1) return o2;
if (!o2) return o1;
if (L[o1] == -1) return o1;
pushdown(o1); pushdown(o2);
for (int i = 0; i < 2; i++)
ch[o1][i] = Merge(ch[o1][i],ch[o2][i]);
if (All[ch[o1][0]] && All[ch[o1][1]]) All[o1] = 1;
return o1;
}
void Insert(int o,int k)
{
if (L[o] == -1) {All[o] = 1; return;}
int Nex = k & (1 << L[o]) ? 1 : 0;
if (!ch[o][Nex]) ch[o][Nex] = ++cnt,L[cnt] = L[o] - 1;
Insert(ch[o][Nex],k);
if (All[ch[o][0]] && All[ch[o][1]]) All[o] = 1;
}
int Query(int o)
{
int ret = 0;
for (int i = T - 1; i >= 0; i--)
{
pushdown(o);
int Nex = All[ch[o][0]] ? 1 : 0;
ret |= (Nex << i); o = ch[o][Nex];
}
return ret;
}
void Dfs(int x,int from)
{
L[rt[x] = ++cnt] = T - 1;
for (int i = 0; i < v[x].size(); i++)
{
int to = v[x][i];
if (to == from) continue;
vis[to] = 1; Dfs(to,x); sum[x] ^= sg[to];
}
for (int i = 0; i < v[x].size(); i++)
{
int to = v[x][i];
if (to == from) continue;
Mark[rt[to]] ^= (sum[x] ^ sg[to]);
rt[x] = Merge(rt[x],rt[to]);
}
Insert(rt[x],sum[x]); sg[x] = Query(rt[x]);
}
int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret * 10 + ch - '0',ch = getchar();
return ret;
}
void Solve()
{
n = getint(); m = getint();
while (m--)
{
int x = getint(),y = getint();
v[x].push_back(y); v[y].push_back(x);
}
for (int i = 1; i <= n; i++)
if (!vis[i]) vis[i] = 1,Dfs(i,0),Ans ^= sg[i];
puts(Ans ? "Alice" : "Bob"); Clear();
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
Case = getint();
while (Case--) Solve();
return 0;
}