POJ 3710 无向图简单环树上删边
结论题,这题关键在于如何转换环,可以用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){//多组样例233 int 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; }