博弈論之樹上刪邊遊戲
阿新 • • 發佈:2018-09-03
turn 利用 一個點 == tar class lse edge string
可以說成是樹上的NIM遊戲嘛
POJ3710
再樹上刪邊,樹是帶環的,然後基本題意還是和NIM遊戲一致
按環分類討論,如果是奇數環
所有後繼SG值都會是偶數,所以這個狀態SG為1
把環縮成一個點+1條邊
如果是偶數環,那麽後繼SG非0,此環SG=1,就將環縮為1個點
對於環,利用tarjan+棧預處理
1 #include<cstdio> 2 #include<cstring> 3 const int maxn=1005; 4 int n,m,top,cnt; 5 bool vis[maxn],ve[maxn]; 6 int g[maxn],w[maxn],s[maxn];7 struct Edge 8 { 9 int t,next; 10 }e[maxn*2]; 11 void insert(int u,int v) 12 { 13 cnt++;e[cnt].t=v;e[cnt].next=g[u];g[u]=cnt; 14 cnt++;e[cnt].t=u;e[cnt].next=g[v];g[v]=cnt; 15 } 16 int dfs(int x) 17 { 18 vis[x]=1; 19 int ans=0; 20 s[++top]=x; 21 for(int tmp=g[x];tmp;tmp=e[tmp].next)22 { 23 if(!ve[tmp]) 24 { 25 ve[tmp]=1;ve[tmp^1]=1; 26 int temp; 27 if(!vis[e[tmp].t]) temp=dfs(e[tmp].t)+1; 28 else 29 { 30 int q=s[top--]; 31 while(q!=e[tmp].t) 32 { 33 w[q]=1; 34 q=s[top--]; 35 } 36 ++top; 37 return 1; 38 } 39 if(w[e[tmp].t]) ans^=(temp)%2; 40 else ans^=temp; 41 } 42 } 43 return ans; 44 } 45 int main() 46 { 47 int T,ans,x,y; 48 while(scanf("%d",&T)==1) 49 { 50 ans=0; 51 while(T--) 52 { 53 memset(g,0,sizeof(g)); 54 memset(vis,0,sizeof(vis)); 55 memset(ve,0,sizeof(ve)); 56 memset(w,0,sizeof(w)); 57 top=0;cnt=1; 58 scanf("%d%d",&n,&m); 59 for(int i=0;i<m;i++) 60 { 61 scanf("%d%d",&x,&y); 62 insert(x,y); 63 } 64 ans^=dfs(1); 65 } 66 if(ans) puts("Sally"); 67 else puts("Harry"); 68 } 69 return 0; 70 }
博弈論之樹上刪邊遊戲