1. 程式人生 > 實用技巧 >Gym102392F Game on a Tree(博弈論)

Gym102392F Game on a Tree(博弈論)

首先我們發現每兩個點會構成一對,他們公用一條邊,且邊集不能共用任何一個點

如果我們可以找到這樣的邊集使得所有點都被選中,那麼bob是必贏的,否則是必輸的

原因是,我們對於每個點都能找到一個對應匹配的點,不論alice選什麼,bob都有的選,直到alice選不到

那麼反之alice必勝,因為alice只要找到一個未匹配點即可。

這裡再簡單分析一下:

1.假設alice選了一個未匹配點,bob不可能直接選到一個未匹配點,不然就能使他們匹配

2.bob只能選一個匹配點,這樣先後手轉換,alice總能找到bob選的對應的匹配點,並且因為我們已經是最大匹配了,所以bob不可能找到未匹配點,否則原來的匹配就不是最大的

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
int h[N],e[N],ne[N],idx;
int f[N];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa){
    f[u]=0;
    int i;
    for
(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; dfs(j,u); f[u]+=f[j]; } if(!f[u]) f[u]=1; else{ f[u]--; } } int main(){ ios::sync_with_stdio(false); memset(h,-1,sizeof h); int i; int n; cin>>n;
for(i=1;i<n;i++){ int a,b; cin>>a>>b; add(a,b); add(b,a); } dfs(1,-1); if(f[1]==0){ cout<<"Bob"<<endl; } else{ cout<<"Alice"<<endl; } return 0; }
View Code