【哈希】【动态规划】[NOIP模拟赛]仔细的检查
nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上。另一天nodgd更无聊,就又画了一张。
这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点u0在第一幅图中编号为u1,在第二副图中编号为u2。
于是,nodgd决定检查一下他画出的两棵树到底是不是一样的。nodgd已经给每棵树的节点都从1到n进行了编号,即每棵树有n个节点。
如果存在一个1到n的排列p1,p2…pn,对于第一幅图中的任意一条边(i,j),在第二幅图中都能找到一条边(pi,pj),则认为这两幅图中的树是一样的。
题目解析:
把整个数hash一下,然后比较,同时按照size进行排序重新建树,最后dfn值进行匹配输出就好了
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iostream>
using namespace std;
const int MAXN=200005;
const int MAXM=400005;
const int IFN=999999999;
const long long MOD=1000000000000007LL;
const int RAN = 10097;
struct node{int v;node *next;};
pair<long long, int> tmp[MAXN+10];
int n;
struct Tree{
int dcnt, dep[MAXN+10], Fa[MAXN+10];
node Edges[MAXM*2 + 10], Edges2[MAXM*2 + 10];
long long hash_val[MAXN+10];
int sz[MAXN+10], dfn[MAXN+10];
node *adj[MAXN+10], *adj2[MAXN+10], *ecnt, *ecnt2;
Tree(){
dcnt=0;
ecnt=Edges;
ecnt2=Edges2;
}
void addedge(int u, int v){
++ecnt;
ecnt->v = v;
ecnt->next = adj[u];
adj[u] = ecnt;
}
void addedge2(int u, int v){
++ecnt2;
ecnt2->v = v;
ecnt2->next = adj2[u];
adj2[u] = ecnt2;
}
void dfs1(int u, int fa){
sz[u] = 1;
for(node *p=adj[u];p;p=p->next){
if(p->v != fa){
dfs1(p->v, u);
sz[u] += sz[p->v];
}
}
int cnt = 0;
for(node *p=adj[u];p;p=p->next)
if(p->v != fa)
tmp[++cnt] = make_pair(hash_val[p->v], p->v);
sort(tmp+1, tmp+1+cnt);
hash_val[u] = (0 ^ sz[u]) % MOD;
for(int i=1;i<=cnt;i++){
hash_val[u] = (hash_val[u] * RAN ^ (tmp[i].first)) % MOD;
addedge2(u, tmp[i].second);
}
}
void dfs2(int u, int fa){
if(u <= n)
dfn[++dcnt] = u;
for(node *p=adj2[u];p;p=p->next)
if(p->v != fa)
dfs2(p->v, u);
}
int FindMID(){
int Max = 0, ret = -1;
queue<pair<int, int> > que;
que.push(make_pair(1, 0));
while(!que.empty()){
pair<int, int> u = que.front(); que.pop();
for(node *p=adj[u.first];p;p=p->next){
if(p->v != u.second){
dep[p->v] = dep[u.first] + 1;
que.push(make_pair(p->v, u.first));
if(dep[p->v] > Max){
Max = dep[p->v];
ret = p->v;
}
}
}
}
que.push(make_pair(ret, 0));
dep[ret] = 0;
Max = 0; ret = -1;
while(!que.empty()){
pair<int, int> u = que.front(); que.pop();
for(node *p=adj[u.first];p;p=p->next){
if(p->v != u.second){
dep[p->v] = dep[u.first] + 1;
que.push(make_pair(p->v, u.first));
if(dep[p->v] > Max){
Max = dep[p->v];
ret = p->v;
}
Fa[p->v] = u.first;
}
}
}
Max /= 2;
int now = ret;
while(Max--)
now = Fa[now];
return now;
}
int Read(){
int u, v;
for(int i=1;i<n;i++){
scanf("%d%d", &u, &v);
addedge(u, n+i); addedge(n+i, u);
addedge(v, n+i); addedge(n+i, v);
}
int md = FindMID();
dfs1(md, -1); dfs2(md, -1);
return hash_val[md];
}
}Tree1, Tree2;
int con[MAXN+10];
int main(){
scanf("%d", &n);
int h1 = Tree1.Read();
int h2 = Tree2.Read();
if(h1 != h2) printf("NO\n");
else{
printf("YES\n");
for(int i=1;i<=n;i++)
con[Tree1.dfn[i]] = Tree2.dfn[i];
for(int i=1;i<=n;i++)
printf("%d ", con[i]);
}
return 0;
}