• 【BZOJ4337】BJOI2015 树的同构 括号序列


    【BZOJ4337】BJOI2015 树的同构

    Description

    树是一种很常见的数据结构。
    我们把N个点,N-1条边的连通无向图称为树。
    若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。
    对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相同,那么这两个树是同构的。也就是说,它们具有相同的形态。
    现在,给你M个有根树,请你把它们按同构关系分成若干个等价类。

    Input

    第一行,一个整数M。
    接下来M行,每行包含若干个整数,表示一个树。第一个整数N表示点数。接下来N个整数,依次表示编号为1到N的每个点的父亲结点的编号。根节点父亲结点编号为0。

    Output

    输出M行,每行一个整数,表示与每个树同构的树的最小编号。

    Sample Input

    4
    4 0 1 1 2
    4 2 0 2 3
    4 0 1 1 1
    4 0 1 2 3

    Sample Output

    1
    1
    3
    1

    HINT

    【样例解释】
    编号为1, 2, 4 的树是同构的。编号为3 的树只与它自身同构。 
    100% 的数据中,1 ≤ N, M ≤ 50。 

    题解:题意有问题,题中的树同构是无根树的同构。。。

    一开始写了个hash,被卡了,于是学了一发高端的做法。

    如果是一棵有根树,那么我们从根开始DFS整棵树,将每个节点的入栈和出栈看成左括号和右括号,最终得到一个括号序列即能代表整棵树。

    那么无根树呢?以重心为根即可。如果有两个重心呢?各跑一遍,然后取字典序较小的那个即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <string>
    using namespace std;
    int n,mn,m,cnt;
    int bel[55],siz[55],to[110],next[110],head[55],mx[55];
    string f[55],p[55],g[55];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
    	return ret*f;
    }
    inline void add(int a,int b)
    {
    	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
    }
    void dfs(int x,int fa)
    {
    	int i,sum=0;
    	for(i=head[x];i!=-1;i=next[i])	if(to[i]!=fa)	dfs(to[i],x);
    	for(i=head[x];i!=-1;i=next[i])	if(to[i]!=fa)	p[++sum]=f[to[i]];
    	f[x]="(";
    	sort(p+1,p+sum+1);
    	for(i=1;i<=sum;i++)	f[x]+=p[i];
    	f[x]+=")";
    }
    void getrt(int x,int fa)
    {
    	mx[x]=0,siz[x]=1;
    	for(int i=head[x];i!=-1;i=next[i])	if(to[i]!=fa)	getrt(to[i],x),siz[x]+=siz[to[i]],mx[x]=max(mx[x],siz[to[i]]);
    	mx[x]=max(mx[x],m-siz[x]);
    	mn=min(mn,mx[x]);
    }
    string get()
    {
    	string tmp="";
    	m=rd();
    	int i,a;
    	memset(head,-1,sizeof(head)),cnt=0;
    	for(i=1;i<=m;i++)
    	{
    		a=rd();
    		if(a)	add(a,i),add(i,a);
    	}
    	mn=1<<30,getrt(1,0);
    	for(i=1;i<=m;i++)	if(mx[i]==mn)
    	{
    		dfs(i,0);
    		tmp=max(tmp,f[i]);
    	}
    	return tmp;
    }
    int main()
    {
    	n=rd();
    	int i,j;
    	for(i=1;i<=n;i++)	g[i]=get();
    	for(i=1;i<=n;i++)
    	{
    		for(j=1;j<i;j++)	if(g[i]==g[j])	break;
    		printf("%d
    ",j);
    	}
    	return 0;
    }//4 4 0 1 1 2 4 2 0 2 3 4 0 1 1 1 4 0 1 2 3 
  • 相关阅读:
    JavaScript获取浏览器高度和宽度值
    机器学习2
    2014.7.23
    2014.7.22
    STM32 定时器
    STM32 外部中断
    STM32--systick延时
    STM32 时钟
    输入捕获
    DAC
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7886956.html
Copyright © 2020-2023  润新知