1. 程式人生 > 實用技巧 >「小結」無向圖刪邊遊戲

「小結」無向圖刪邊遊戲

一、樹的刪邊遊戲

給出一棵有根樹,兩人輪流操作,每人每次可以選擇一條邊刪去,不與根節點相連的部分將被移走。無法操作者輸。

結論:葉子節點的 \(\text{SG}\) 值為 \(0\);中間節點的 \(\text{SG}\) 值為它的所有子節點的「\(\text{SG}\) 值加 \(1\)」的異或和。這樣就可以推出根節點的\(\text{SG}\)值。證明

二、POJ 3710 Christmas Game

Description

\(n\) 個區域性連通的圖,兩人輪流操作,每人每次可以選擇一條邊刪去,不與根節點相連的部分將被移走。無法操作者輸。(圖是通過從基礎樹上加一些邊得到的,環與環之間無公共邊,且只與基礎樹有一個公共點。)

Solution

與「樹的刪邊遊戲」不同的在於圖中出現了環。所以環可以單獨考慮。

分析環的性質:環保證不共用邊,且只與基礎樹有一個公共點。因此所有的環都是從樹中某一個點連出又連回同一個點的簡單環。

  • 對於長度為奇數的環,去掉其中任意一條邊後,剩下的兩個鏈長度同奇偶,異或之後的\(\text{SG}\)值不可能為奇數,並且可能為\(0\)。所以進行 \(\text{mex}\) 運算後它的 \(\text{SG}\) 值為 \(1\)
  • 對於長度為奇數的環,去掉其中任意一條邊後,剩下的兩個鏈長度不同奇偶,異或之後的\(\text{SG}\)值不可能為 \(0\)。所以進行 \(\text{mex}\)
    運算後它的 \(\text{SG}\) 值為 \(0\)。實際上它並沒有貢獻。

所以可以去掉所有的偶環,將所有的奇環變為長度為\(1\) 的鏈,轉化為「樹的刪邊遊戲」的模型。

算出每一棵樹的 \(\text{SG}\) 值,再把所有根節點的\(\text{SG}\)值異或起來即可。

具體實現時,不需要做「將所有的奇環變為長度為\(1\)的鏈」的操作,只需考慮奇環的貢獻。

#include<cstdio>
#define int long long
using namespace std;
const int N=1e5+5;
int t,n,m,x,y,cnt,hd[N],to[N<<1
],nxt[N<<1],top,s[N],sg[N],vis[N],ans; //vis=0: 未訪問過 vis=1: 訪問過且不是某個環上的點(不考慮樹上的點) vis=-1: 訪問過且是某個環上的點 void add(int x,int y){ to[++cnt]=y,nxt[cnt]=hd[x],hd[x]=cnt; } void dfs(int x,int fa){ s[++top]=x,vis[x]=1,sg[x]=0; bool flag=0; for(int i=hd[x];i;i=nxt[i]){ int y=to[i]; if(y==fa&&!flag){flag=1;continue;} //第一次連向父節點 if(vis[y]==1){ int cnt=1,now=x; while(now!=y) cnt++,vis[now]=-1,now=s[--top]; if(cnt&1) sg[y]^=1; //奇環 } else if(!vis[y]){ dfs(y,x); if(~vis[y]) sg[x]^=(sg[y]+1); //不在環上的才能更新 } } if(~vis[x]) --top; //非環上的,及時出棧 } signed main(){ while(~scanf("%lld",&t)){ ans=0; while(t--){ scanf("%lld%lld",&n,&m),cnt=top=0; for(int i=1;i<=n;i++) hd[i]=vis[i]=0; for(int i=1;i<=m;i++){ scanf("%lld%lld",&x,&y); add(x,y),add(y,x); } dfs(1,0),ans^=sg[1]; //根節點的 SG 值異或起來 } puts(ans?"Sally":"Harry"); } return 0; }

三、圖的刪邊遊戲

「POJ3710 Christmas Game」去掉環的限制。即:給定一個無向連通圖,有一個點作為圖的根。兩人輪流操作,每人每次可以從圖中選擇一條邊刪去,不與根節點相連的部分將被移走。無法操作者輸。

對於這個模型,有一個定理——Fusion Principle。

結論:對無向圖做如下改動:將圖中的任意一個偶環縮成一個新點,任意一個奇環縮成一個新點加一條新邊;所有連到原先環上的邊全部改為與新點相連。這樣的改動不會影響圖的\(\text{SG}\)值。

因此可以將任意一個無向圖改成樹結構。然後就能把「圖的刪邊遊戲」轉化為「樹的刪邊遊戲」了。

四、參考資料