可以说成是树上的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 }