• Jzoj5454【NOIP2017提高A组冲刺11.5】仔细的检查


    nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上。另一天nodgd更无聊,就又画了一张。
    这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点u0在第一幅图中编号为u1,在第二副图中编号为u2。
    于是,nodgd决定检查一下他画出的两棵树到底是不是一样的。nodgd已经给每棵树的节点都从1到u进行了编号,即每棵树有n个节点。

    如果存在一个1到n的排列p1p2…pn,对于第一幅图中的任意一条边(u,v),在第二幅图中都能找到一条边(pu,pv),则认为这两幅图中的树是一样的。

    又是一道树同构啊,今年第一篇文章就写了这个啊

    见题秒,but,求p数组的时候写挂了。。。

    简单说一下,基本思想就是对树的括号序列求rabin-karp

    这里是无根树所以可以选出树的重心做根

    让后对所有子树排序后跑一次dfs序,记为a和b,那么就有p[a[i]]=b[i]

    让后?没有了啊

    #include<vector>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define LL long long
    using namespace std;
    LL pow(LL x,LL k){
    	LL s=1;
    	for(;k;x=x*x,k>>=1) if(k&1) s=s*x;
    	return s;
    }
    struct rk{ int len; LL val; } *CC;
    inline rk operator+ (rk a,rk b){
    	return (rk){a.len+b.len,a.val*pow(313,b.len)+b.val};
    }
    inline bool operator < (rk a,rk b){ return a.val<b.val; }
    inline bool cmp(int x,int y){ return CC[x]<CC[y]; } 
    struct rabin_karp{
    	int f[100010],sz[100010],r[100010],n,tot,cnt,rt;
    	vector<int> G[100010]; rk c[100010];
    	inline void clear(int N){
    		memset(f,0,sizeof f);
    		memset(r,0,sizeof r);
    		n=N; cnt=tot=0; rt=0; f[0]=1<<30;
    	}
    	inline void adj(int x,int y){
    		G[x].push_back(y);
    		G[y].push_back(x); 
    	}
    	void gRt(int x,int p){
    		sz[x]=f[x]=1;
    		for(int i=0,z=G[x].size(),v;i<z;++i)
    			if((v=G[x][i])!=p){
    				gRt(v,x);
    				sz[x]+=sz[v];
    				f[x]=max(f[x],sz[v]);
    			}
    		f[x]=max(f[x],n-sz[x]);
    		if(f[x]<f[rt]) rt=x;
    	}
    	void dfs(int x,int p){
    		c[x]=(rk){0,0};
    		for(int i=0,z=G[x].size(),v;i<z;++i)
    			if((v=G[x][i])!=p) dfs(v,x);
    		sort(G[x].begin(),G[x].end(),cmp);
    		for(int i=0;i<G[x].size();++i){
    			c[x]=c[x]+c[G[x][i]]; 
    		}
    		c[x]=(rk){1,(LL)'('}+c[x]+(rk){1,(LL)')'};
    	}
    	void dgs(int x,int p){
    		r[++tot]=x;
    		for(int i=0,z=G[x].size(),v;i<z;++i)
    			if((v=G[x][i])!=p) dgs(v,x);
    	}
    	void cal(){ CC=c; gRt(1,0); dfs(rt,0); dgs(rt,0); }
    } a,b;
    int p[100010],n;
    int main(){
    	freopen("check.in","r",stdin);
    	freopen("check.out","w",stdout);
    	scanf("%d",&n);
    	a.clear(n); b.clear(n);
    	for(int x,y,i=1;i<n;++i){
    		scanf("%d%d",&x,&y);
    		a.adj(x,y);
    	}
    	for(int x,y,i=1;i<n;++i){
    		scanf("%d%d",&x,&y);
    		b.adj(x,y);
    	}
    	a.cal(); b.cal();
    	if(a.c[a.rt].val!=b.c[b.rt].val) return 0&puts("NO");
    	else for(int i=1;i<=n;++i) p[a.r[i]]=b.r[i];
    	puts("YES");
    	for(int i=1;i<=n;++i) printf("%d ",p[i]);
    }

  • 相关阅读:
    python关于字典如何格式化地写入文件之中
    关于python如何安装和配置chromedriver以及一些相关问题
    python编码的原理以及写入文件中乱码的原因
    json到底是什么??????
    scrapy框架Request函数callback参数为什么是self.parse而不是self.parse( )
    scrapy框架xpath的几点说明
    python基于scrapy框架的反爬虫机制破解之User-Agent伪装
    HTML,CSS,JavaScript,json,xml之间的关系
    scrapy框架在未登录模式下爬取文本,文件和图片的几点收获
    scrapy爬虫提取网页链接的两种方法以及构造HtmlResponse对象的方式
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477240.html
Copyright © 2020-2023  润新知