【哈希】【动态规划】[NOIP模拟赛]仔细的检查
2015-11-04 13:33
519 查看
nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上。另一天nodgd更无聊,就又画了一张。
这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点u0在第一幅图中编号为u1,在第二副图中编号为u2。
于是,nodgd决定检查一下他画出的两棵树到底是不是一样的。nodgd已经给每棵树的节点都从1到n进行了编号,即每棵树有n个节点。
如果存在一个1到n的排列p1,p2…pn,对于第一幅图中的任意一条边(i,j),在第二幅图中都能找到一条边(pi,pj),则认为这两幅图中的树是一样的。
题目解析:
把整个数hash一下,然后比较,同时按照size进行排序重新建树,最后dfn值进行匹配输出就好了
这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点u0在第一幅图中编号为u1,在第二副图中编号为u2。
于是,nodgd决定检查一下他画出的两棵树到底是不是一样的。nodgd已经给每棵树的节点都从1到n进行了编号,即每棵树有n个节点。
如果存在一个1到n的排列p1,p2…pn,对于第一幅图中的任意一条边(i,j),在第二幅图中都能找到一条边(pi,pj),则认为这两幅图中的树是一样的。
题目解析:
把整个数hash一下,然后比较,同时按照size进行排序重新建树,最后dfn值进行匹配输出就好了
[code]#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; }
相关文章推荐
- *hdu 5536(字典树的运用)
- python re 里面match 和search的区别
- web.xml中的contextConfigLocation在spring中的作用
- java 文件的压缩
- linux sort 命令
- 将Eclipse包括第一3正方形jar包裹Project Export并产生能够执行jar
- objective-c基础教程——学习小结
- Android开发把项目打包成apk
- 既然有了elasticsearch为什么还要用hadoop和spark呢?good question
- 什么方法将txt转换pdf最有效
- mysql性能测试及不同版本的比较
- 【贪心】[NOIP模拟赛]奇怪的队列
- 杭电ACM 1041 Computer Transformation java代码详解AC
- Win7 64位下安装pomelo 1.2.0
- 鸟哥的Linux私房菜(基础篇)- 第二十二章、软件安装:原始码与 Tarball
- linux 下名称改为bogon
- alpha版、beta版、rc版的意思
- Java的四种引用类型
- XML中输入特殊符号
- DP--UVA - 437 The Tower of Babylon