## uva12489 Combating cancer(树同构)

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3933

/**
* code generated by JHelper
* @author xyiyy @https://github.com/xyiyy
*/

#include <iostream>
#include <fstream>

//#####################
//Author:fraud
//Blog: http://www.cnblogs.com/fraud/
//#####################
#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype>

using namespace std;
#define pb(X) push_back(X)
#define rep(X, N) for(int X=0;X<N;X++)
#define ALL(X) (X).begin(),(X).end()
typedef unsigned long long ull;

const int maxNode = 10010;
const int maxEdge = (maxNode << 1);
//
// Created by xyiyy on 2015/8/14.
//

#ifndef ICPC_HASHTREE_HPP
#define ICPC_HASHTREE_HPP

//树的同构，返回哈希值
//输入有根树的根，或者无根树的重心
typedef unsigned long long ull;
const ull MAGIC = 321;

//
// Created by xyfra_000 on 2015/8/14.
//

#define Foredge(A, X) for(int A = From[X];A!=-1;A = Next[A])

int From[maxEdge], To[maxEdge];
int Next[maxEdge];
int Edgecnt;

void init(int n) {
rep(i, n + 1)From[i] = -1;
Edgecnt = 0;
}

void addedge(int u, int v) {
To[Edgecnt] = v;
Next[Edgecnt] = From[u];
From[u] = Edgecnt++;
}

ull powMod(ull a, int n) {
ull ret = 1ULL;
while (n) {
if (n & 1)ret *= a;
a *= a;
n >>= 1;
}
return ret;
}

struct Hash {
int length;
ull value;

Hash() : length(0), value(0) { }

Hash(char c) : length(1), value(c) { }

Hash(int l, int v) : length(l), value(v) { }
};

bool operator<(const Hash &a, const Hash &b) {
return a.value < b.value;
}

Hash operator+(const Hash &a, const Hash &b) {
return Hash(a.length + b.length, a.value * powMod(MAGIC, b.length) + b.value);
}

void operator+=(Hash &a, Hash &b) {
a = a + b;
}

vector<Hash> childs[maxNode];

Hash dfs(int pre, int cur) {
Hash ret;
childs[cur].clear();
for (int iter = From[cur]; iter != -1; iter = Next[iter]) {
if (To[iter] != pre) {
childs[cur].pb(dfs(cur, To[iter]));
}
}
sort(ALL(childs[cur]));
for (vector<Hash>::iterator iter = childs[cur].begin(); iter != childs[cur].end(); iter++) {
ret += *iter;
}
Hash retL = Hash('(');
ret = '(' + ret + ')';
return ret;
}

ull getHash(int root) {
return dfs(-1, root).value;
}

#endif //ICPC_HASHTREE_HPP

//
// Created by xyfra_000 on 2015/8/14.
//

#ifndef ICPC_TREEDIAMETER_HPP
#define ICPC_TREEDIAMETER_HPP

//求树的直径
//可以通过修改dfs部分变成求带权的树的直径

vector<int> dist;

void dfs(int p, int u, int d) {
dist[u] = d;
Foredge(i, u) {
if (To[i] != p) {
dfs(u, To[i], d + 1);
}
}
}

int getDiameter(int n) {
dist.resize(n);
dfs(-1, 0, 0);
int u = max_element(ALL(dist)) - dist.begin();
dfs(-1, u, 0);
return *max_element(ALL(dist));
}

#endif //ICPC_TREEDIAMETER_HPP

int deg[maxNode];
int vis[maxNode];

public:
void solve(std::istream &in, std::ostream &out) {
int n;
while (in >> n) {
vector<ull> ans[2];
rep(times, 2) {
int u, v;
init(n);
rep(i, n + 1)deg[i] = 0;
rep(i, n + 1)vis[i] = 0;
queue<int> q;
rep(i, n - 1) {
in >> u >> v;
u--, v--;
deg[u]++;
deg[v]++;
}
int dia = getDiameter(n);
int num = n;
rep(i, n) {
if (deg[i] == 1) {
q.push(i);
}
}
int gao = 1;
if (dia & 1)gao++;
while (num > gao && !q.empty()) {
u = q.front();
q.pop();
vis[u] = 1;
num--;
deg[u]--;
for (int i = From[u]; i != -1; i = Next[i]) {
int v = To[i];
if (!vis[v]) {
deg[v]--;
if (deg[v] == 1) {
q.push(v);
}
}
}
}
rep(i, n) {
if (!vis[i]) {
ans[times].pb(getHash(i));
}
}
}
bool ok = 0;
rep(i, ans[0].size()) {
rep(j, ans[1].size()) {
if (ans[0][i] == ans[1][j])ok = 1;
}
}
if (ok)out << "S" << endl;
else out << "N" << endl;
}
}
};

int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::istream &in(std::cin);
std::ostream &out(std::cout);
solver.solve(in, out);
return 0;
}

posted on 2015-08-14 20:46  xyiyy  阅读(...)  评论(...编辑  收藏

• 随笔 - 102
• 文章 - 0
• 评论 - 7
• 引用 - 0