Christmas Game POJ - 3710
- 无向图缩环变树
- 树删边博弈
边连通分量缩成一个点
#include<iostream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<cmath>
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define Pb push_back
#define FI first
#define SE second
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define IOS ios::sync_with_stdio(false)
#define DEBUG cout<<endl<<"DEBUG"<<endl;
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int prime = 999983;
const int INF = 0x7FFFFFFF;
const LL INFF =0x7FFFFFFFFFFFFFFF;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-6;
const LL mod = 1e9 + 7;
LL qpow(LL a,LL b){LL s=1;while(b>0){if(b&1)s=s*a%mod;a=a*a%mod;b>>=1;}return s;}
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
int dr[2][4] = {1,-1,0,0,0,0,-1,1};
typedef pair<int,int> P;
vector<P> edges;
const int maxn = 1e6+100;
int pre[maxn];
int dfs_clock = 0;
vector<int> G[maxn];
vector<int> G2[maxn];
int low[maxn];
int father[maxn];
bool vis[maxn];
int belong[maxn];
int num[maxn];
void init(int m){
dfs_clock = 0;
rep(i,1,m+1) G[i].clear(),G2[i].clear();
memset(low,0,sizeof(low[0])*(m+1));
memset(pre,0,sizeof(pre[0])*(m+1));
memset(vis,0,sizeof(vis[0])*(m+1));
memset(num,0,sizeof(num[0])*(m+1));
memset(belong,0,sizeof(belong[0])*(m+1));
}
int dfs1(int u,int fa){
father[u] = fa;
int lowu = pre[u] = ++dfs_clock;
int tofa = 0;
for(int i = 0;i < (int)G[u].size(); ++i){
int v = G[u][i];
if(!pre[v]){
int lowv = dfs1(v,u);
lowu = min(lowu,lowv);
}
else if( v != fa){
lowu = min(lowu,pre[v]);
}
else if(v == fa)
{
if(tofa)
lowu = min(lowu,pre[v]);
tofa++;
}
}
return low[u] = lowu;
}
bool Is_bridge(int u,int v){
if(father[v] != u&&father[u] != v) return 0;
return (pre[v] == low[v]);
}
void dfs(int u,int be){
belong[u] = be;
for(int i = 0;i < (int)G[u].size(); ++i){
int v = G[u][i];
if(belong[v]) continue;
if(Is_bridge(u,v)) continue;
dfs(v,be);
}
}
int SG(int u,int fa){
vis[u] = 1;
int t = 0;
for(int i = 0;i < (int)G2[u].size(); ++i){
int v = G2[u][i];
if(vis[v]) continue;
t ^= (SG(v,u)+1);
}
if(num[u]&1) t ^= 1;
return t;
}
int main(void)
{
int n,m,k;
cin>>n;
while(n--){
int sum = 0;
edges.clear();
scanf("%d%d",&m,&k);
init(m);
rep(i,0,k){
int u,v;
scanf("%d%d",&u,&v);
G[u].Pb(v);
G[v].Pb(u);
edges.Pb(P(u,v));
}
dfs1(1,-1);
int tot = 0;
rep(i,1,m+1)
if(!belong[i])
dfs(i,++tot);
for(int i = 0;i < (int)edges.size(); i ++){
int x = belong[edges[i].first];
int y = belong[edges[i].second];
if(x != y)
G2[x].Pb(y),G2[y].Pb(x);
else
num[x]++;
}
sum ^= SG(1,-1);
if (sum) cout << "Alice\n"; else cout << "Bob\n";
}
return 0;
}