结论题,这题关键在于如何转换环,可以用tarjan求出连通分量后再进行标记,也可以DFS直接找到环后把点的SG值变掉就行了
/** @Date : 2017-10-23 19:47:47* @FileName: POJ 3710 简单环 树上删边 DFS.cpp* @Platform: Windows* @Author : Lweleth (SoungEarlf@gmail.com)* @Link : https://github.com/* @Version : $Id$*/
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <stack>
#include <queue>
#include <math.h>
//#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;const int INF = 0x3f3f3f3f;
const int N = 1e3 + 20;
const double eps = 1e-8;struct node{int nxt, to;
}edg[N*2];int vis[N];
int head[N*2];
int tot;
int st[10010], top;int sg[N];void init()
{MMG(head);MMG(vis); MMF(sg);tot = top = 0;
}inline void add(int x, int y)
{edg[tot].nxt = head[x];edg[tot].to = y;head[x] = tot++;
}void dfs(int x, int pre)
{st[++top] = x;vis[x] = 1;int flag = 0;for(int i = head[x]; ~i; i = edg[i].nxt){if(edg[i].to == pre && !flag){flag = 1;continue;}if(vis[edg[i].to] == 1){int nw = st[top];int cnt = 1;while(nw != edg[i].to)vis[nw] = 0, nw = st[--top], cnt++;if(cnt & 1)//奇数环变边sg[edg[i].to] ^= 1;}else if(vis[edg[i].to] == -1){dfs(edg[i].to, x);if(vis[edg[i].to])sg[x] ^= sg[edg[i].to] + 1;}}if(vis[x])top--;
}
int main()
{int T;while(cin >> T){//多组样例233int ans = 0;while(T--){int n, m;scanf("%d%d", &n, &m);init();for(int i = 1; i <= m; i++){int x, y;scanf("%d%d", &x, &y);add(x, y);add(y, x);}dfs(1, -1);ans ^= sg[1];}printf("%s\n", ans?"Sally":"Harry");}return 0;
}