JZOJ5454. 【NOIP2017提高A组冲刺11.5】仔细的检查
来源:互联网 发布:nginx 路径重定向 编辑:程序博客网 时间:2024/05/16 08:29
题目
Sample Input
输入1:
3
1 2
2 3
1 3
3 2
输入2:
4
1 2
2 3
3 4
1 2
1 3
1 4
Sample Output
输出1:
YES
1 3 2
输出2:
NO
题解
题目有两问,
1、判断树是否同构。
2、找出对应点。
对应第一问,考虑树的特征。
考虑每一个节点的特征有什么因素决定:
1、它儿子的特征
2、以它为根的子树大小
3、它的儿子个数
4、它的深度
现在就要把这些决定某个节点的因素变为一个东西。
设
一般只有按照相同的规则将这些决定因素融合成一个数,
那么这个数就是它的特征值了,
建议几个数合并的时候不要用加法,可以选择异或,次方相乘等不容易相同的方法,还可以乘上相应的系数。
关于模数,建议使用c++中的unsigned long long
现在判断是否同构就只需要判断这两棵树的根节点的特征值是否相同就可以了,
而求一次树的特征值的复杂度是O(n),通过换根的方法就可以快速判断两棵树是否同构,并且找出他它们同构的根节点。
之后就是要将所有点一一对应了,递归处理,
对于一个点的所有儿子,将它们的特征值排序,然后跟另一棵树对应。
本题的关键就是如何将一棵树的特征快速地表现出来。
code
#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#define N 100003#define tt 23333#define w 8888888#define ull unsigned long longusing namespace std;int n,m,nxt1[N*2],to1[N*2],b1[N],tot1,nxt2[N*2],to2[N*2],b2[N],tot2;int son1[N],son2[N],si1[N],si2[N],x,y,ans[N],root;ull f1[N],f2[N];struct node{ int x; ull y;}p1[N],p2[N],t;bool cmp(node a,node b){ return a.y<b.y;}char ch;void read(int& n){ n=0; for(ch=getchar();ch<'0' || ch>'9';ch=getchar()); for(;'0'<=ch && ch<='9';n=(n<<3)+(n<<1)+ch-48,ch=getchar());}ull F(ull x,ull y){ return (x*x*tt+y*y*tt)*(w+x+y);}void ins1(int x,int y){ nxt1[++tot1]=b1[x]; to1[tot1]=y; b1[x]=tot1;}void ins2(int x,int y){ nxt2[++tot2]=b2[x]; to2[tot2]=y; b2[x]=tot2;}void dfs1(int x,int fa){ si1[x]=1; for(int i=b1[x];i;i=nxt1[i]) if(to1[i]!=fa) { dfs1(to1[i],x); son1[x]++; si1[x]+=si1[to1[i]]; f1[x]+=f1[to1[i]]; } f1[x]=f1[x]+F(son1[x],si1[x]);}void dfs2(int x,int fa){ si2[x]=1; for(int i=b2[x];i;i=nxt2[i]) if(to2[i]!=fa) { dfs2(to2[i],x); son2[x]++; si2[x]+=si2[to2[i]]; f2[x]+=f2[to2[i]]; } f2[x]=f2[x]+F(son2[x],si2[x]);}void exchange(int x,int y){ f2[x]=f2[x]-f2[y]-F(son2[x],si2[x]); son2[x]--;si2[x]-=si2[y]; f2[x]+=F(son2[x],si2[x]); f2[y]-=F(son2[y],si2[y]); son2[y]++;si2[y]=n; f2[y]+=f2[x]+F(son2[y],si2[y]);}void work(int x,int fa){ if(f2[x]==f1[1])root=x; if(root)return; for(int i=b2[x];i;i=nxt2[i]) if(to2[i]!=fa) { exchange(x,to2[i]); work(to2[i],x); if(root)return; exchange(to2[i],x); }}void solve(int x1,int fa1,int x2,int fa2){ int ttt=0; for(int i=b1[x1];i;i=nxt1[i]) if(to1[i]!=fa1) { t.x=to1[i];t.y=f1[t.x]; p1[++ttt]=t; } ttt=0; for(int i=b2[x2];i;i=nxt2[i]) if(to2[i]!=fa2) { t.x=to2[i];t.y=f2[t.x]; p2[++ttt]=t; } sort(p1+1,p1+1+son1[x1],cmp); sort(p2+1,p2+1+son2[x2],cmp); for(int i=1;i<=son1[x1];i++) ans[p1[i].x]=p2[i].x; for(int i=b1[x1];i;i=nxt1[i]) if(to1[i]!=fa1)solve(to1[i],x1,ans[to1[i]],x2);}int main(){ freopen("check.in","r",stdin); freopen("check.out","w",stdout); read(n); for(int i=1;i<n;i++) read(x),read(y),ins1(x,y),ins1(y,x); for(int i=1;i<n;i++) read(x),read(y),ins2(x,y),ins2(y,x); dfs1(1,0); dfs2(1,0); root=0; work(1,0); if(root==0) { printf("NO\n"); return 0; } ans[1]=root; solve(1,0,root,0); printf("YES\n"); for(int i=1;i<=n;i++) printf("%d ",ans[i]); return 0;}
阅读全文
0 0
- Jzoj5454【NOIP2017提高A组冲刺11.5】仔细的检查
- JZOJ5454. 【NOIP2017提高A组冲刺11.5】仔细的检查
- JZOJ5454. 【NOIP2017提高A组冲刺11.5】仔细的检查 树hash
- 【ZJOJ 5454】【NOIP2017提高A组冲刺11.5】仔细的检查
- JZOJ 5454. 【NOIP2017提高A组冲刺11.5】仔细的检查
- [JZOJ5454]仔细的检查
- 【NOIP2017提高组】仔细的检查
- 【NOIP2017提高A组冲刺11.5】轰炸
- 【NOIP2017提高A组冲刺11.5】总结
- [JZOJ5456]【NOIP2017提高A组冲刺11.6】奇怪的队列
- Jzoj5456【NOIP2017提高A组冲刺11.6】奇怪的队列
- JZOJ5456. 【NOIP2017提高A组冲刺11.6】奇怪的队列
- 【JZOJ 5452】【NOIP2017提高A组冲刺11.5】轰炸
- JZOJ 5452. 【NOIP2017提高A组冲刺11.5】轰炸
- JZOJ 5453. 【NOIP2017提高A组冲刺11.5】好路线
- Jzoj5453【NOIP2017提高A组冲刺11.5】好路线
- JZOJ5453. 【NOIP2017提高A组冲刺11.5】好路线
- Jzoj5452【NOIP2017提高A组冲刺11.5】轰炸
- 面向对象的三大特性:封装,继承,多态
- 用VMware虚拟机打开Ubuntu报错:“锁定文件失败”
- 在Ubuntu 16.04下安装Matlab 2017a
- centos7下安装oracle11g
- Java并发编程:CopyOnWriteArrayList
- JZOJ5454. 【NOIP2017提高A组冲刺11.5】仔细的检查
- 使用Scrapy爬取股票数据
- JS基础
- 单元测试的重要性【转自”至简李云“博客】
- linux内核分析-简单的操作系统内核源码解读
- 四周一次课(11月6日) 8.1 类的一般形式 8.2 python构造器 8.3 类的继承
- 关于Python列表的去重
- Hbase入门
- POJ