【哈希】【动态规划】[NOIP模拟赛]仔细的检查
来源:互联网 发布:产品外观结构设计软件 编辑:程序博客网 时间:2024/05/22 07:51
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;}
1 0
- 【哈希】【动态规划】[NOIP模拟赛]仔细的检查
- NOIP模拟 杆子的排列 【动态规划】
- 【动态规划】[NOIP 模拟赛]密码
- [NOIP模拟][动态规划]permut
- [NOIP模拟][动态规划]hello
- NOIP模拟 table 动态规划
- [NOIP模拟][动态规划]Table
- NOIP模拟 边的处理【分治+动态规划】
- 【动态规划】【图论】[NOIP模拟赛]独立集
- [NOIP模拟][动态规划]随机图
- NOIP模拟 分玩具【博弈论】【动态规划】
- NOIP模拟 Game 【博弈论】【动态规划】
- NOIP模拟 回文子串【动态规划】
- [JZOJ5454]仔细的检查
- NOIP模拟题 2016.11.14 [动态规划] [线段树优化DP] [字符串的复制粘贴DP]
- 【动态规划】【图论最长路】[NOIP模拟赛]益智游戏
- NOIP模拟题 2016.9.10 [动态规划] [概率] [贪心]
- [NOIP模拟][记忆化搜索][动态规划]游戏
- ActiveMQ学习总结(5)——Java消息服务JMS详解
- boost camp 分区失败处理方法
- ThinkPad T440 Win10系统长时间睡眠之后无法唤醒的问题
- 关于DES加密,适用Andriod、iOS与JAVA后台
- python re 里面match 和search的区别
- 【哈希】【动态规划】[NOIP模拟赛]仔细的检查
- iOS中显示自带地图(高德地图)的大头针
- 最快遍历完图中重要节点 树的直径 Codeforces 328 (Div. 2) D. Super M
- 计算几何与图形学有关的几种常用算法(一)
- Android 中轴旋转特效实现,制作别样的图片浏览器
- On Hat Puzzle 1.2: Solutions
- Spring in action 学习(2)创建Bean
- 乔布斯是如何形象解释 OOP 的
- 解决Delphi开发DLL中窗体按钮显示状态不刷新问题.