zoukankan      html  css  js  c++  java
  • luogu4323 独特的树叶

    题目描述

    JYY有两棵树 A 和 B :树 A 有 N 个点,编号为 1 到 N ;树 B 有N+1 个节点,编号为 1 到N+1

    JYY 知道树 B 恰好是由树 A 加上一个叶节点,然后将节点的编号打乱后得到的。他想知道,这个多余的叶子到底是树 B 中的哪一个叶节点呢?

    输入格式

    输入一行包含一个正整数 N。 接下来 N−1 行,描述树A,每行包含两个整数表示树 A 中的一条边; 接下来 N 行,描述树 B,每行包含两个整数表示树 B 中的一条边。

    输出格式

    输出一行一个整数,表示树 B 中相比树 A 多余的那个叶子的编号。如果有多个符合要求的叶子,输出 B 中编号最小的那一个的编号。

    输入输出样例

    输入

    5
    1 2
    2 3
    1 4
    1 5
    1 2
    2 3
    3 4
    4 5
    3 6
    

    输出

    1
    

    说明/提示

    对于所有数据,(1 leq n leq 10 ^ 5)


    求出A树中所有点为根的树哈希值,并排序!
    求出B树中所有点为根的树哈希值,从小到大枚举每一个叶子,如果它连接的点的哈希值减去这个叶子对它的贡献(为2)可以在A树所有哈希值中找到则输出,并结束程序!


    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    struct edge
    {
    	int u,v,nxt;
    }e[maxn<<1],ee[maxn<<1];
    int head[maxn],js,headd[maxn],jss;
    void addage(int u,int v)
    {
    	e[++js].u=u;e[js].v=v;
    	e[js].nxt=head[u];head[u]=js;
    }
    void addagee(int u,int v)
    {
    	ee[++jss].u=u;ee[jss].v=v;
    	ee[jss].nxt=headd[u];headd[u]=jss;
    }
    int n;
    bool noprime[(int)2e6+10];
    int prime[maxn],cnt;
    void getprime()
    {
    	for(int i=2;i<2e6+10;++i)
    	{
    		if(cnt>n)return;
    		if(!noprime[i])prime[++cnt]=i;
    		for(int j=1;j<=cnt;++j)
    		{
    			if(i*prime[j]>2e6)break;
    			noprime[i*prime[j]]=1;
    			if(i%prime[j]==0)break;
    		}
    	}	
    }
    int f[maxn],siz[maxn],g[maxn];
    void dfs(int u,int fa)
    {
    	f[u]=siz[u]=1;
    	for(int i=head[u];i;i=e[i].nxt)
    	{
    		int v=e[i].v;
    		if(v==fa)continue;
    		dfs(v,u);
    		siz[u]+=siz[v];
    		f[u]+=f[v]*prime[siz[v]];
    	}
    }
    void getg(int u,int fa,int faf)
    {
    	for(int i=head[u];i;i=e[i].nxt)
    	{
    		int v=e[i].v;
    		if(v==fa)continue;
    		int tp=f[u]-f[v]*prime[siz[v]]+faf*prime[n-siz[u]];
    		g[v]=f[v]+tp*prime[n-siz[v]];
    		getg(v,u,tp);
    	}
    }
    int ff[maxn],sizz[maxn],gg[maxn];
    void dfss(int u,int fa)
    {
    	ff[u]=sizz[u]=1;
    	for(int i=headd[u];i;i=ee[i].nxt)
    	{
    		int v=ee[i].v;
    		if(v==fa)continue;
    		dfss(v,u);
    		sizz[u]+=sizz[v];
    		ff[u]+=ff[v]*prime[sizz[v]];
    	}
    }
    void getgg(int u,int fa,int faf)
    {
    	for(int i=headd[u];i;i=ee[i].nxt)
    	{
    		int v=ee[i].v;
    		if(v==fa)continue;
    		int tp=ff[u]-ff[v]*prime[sizz[v]]+faf*prime[n+1-sizz[u]];
    		gg[v]=ff[v]+tp*prime[n+1-sizz[v]];
    		getgg(v,u,tp);
    	}
    }
    int du[maxn],mnd[maxn];
    int main()
    {
    	scanf("%d",&n);
    	getprime();
    	for(int u,v,i=1;i<n;++i)
    	{
    		scanf("%d%d",&u,&v);
    		addage(u,v);addage(v,u);
    	}
    	for(int u,v,i=1;i<=n;++i)
    	{
    		scanf("%d%d",&u,&v);
    		addagee(u,v);addagee(v,u);
    		++du[u];++du[v];
    	}
    	dfs(1,0);
    	g[1]=f[1];
    	getg(1,0,0);
    	sort(g+1,g+1+n);
    	dfss(1,0);
    	gg[1]=ff[1];
    	getgg(1,0,0);
    	for(int u=1;u<n+1;++u)
    	{
    		if(du[u]!=1)continue;
    		int i=headd[u];
    		int w=gg[ee[i].v]-2;
    		int tp=lower_bound(g+1,g+1+n,w)-g;
    		if(tp>n)continue;
    		if(g[tp]==w)
    		{
    			printf("%d",u);
    			return 0;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    很有意思的“老黄历”网站
    ubuntu
    getopt在Python中的使用
    系统变量TERM不知是用来干什么的?它的值有vt100,vt220等,这些值代表什么意思?
    >/dev/null 2>&1
    linux下常用的ftp服务器软件
    Windows环境下访问NFS
    linux iSCSI target配置全过程
    iSCSI target在安全方面相关设定
    folly学习心得
  • 原文地址:https://www.cnblogs.com/gryzy/p/15266576.html
Copyright © 2011-2022 走看看