zoukankan      html  css  js  c++  java
  • 树的最小表示法 UVA 12489

    mark一下:

    对于一个有根树,我们可以通过比较他们的括号序列的最小表示,如果他们的括号序列最小表示完全相等,那么他们同构

    https://www.byvoid.com/blog/directed-tree-bracket-sequence

    dfs进入某个子树用 '(' 表示,dfs结束用')'表示,这样就将一颗树转化成一个括号序列

    只需将括号序列变成最小表示,就可以比较两棵树是否同构。但复杂度好像很高的样子...

    回到树上来说,比较两棵子树的大小,可以先比较两个顶点的度,如果度相等,则递归比较子树。则可以看成是求一个最小的度序列

    括号序列的另一个理解,就是poj上某道题。'('可以看成0,可以理解为向远离根节点的节点走,')'可以看成1,回溯,往回走。

    于是比较两棵子树的大小,可以将两个01序列,看做为字符串,求最小表示。

    不管是哪种序列,都可以作为树的最小表示。序列求出来,我们可以用 子序列排序+hash 得到一个新的序列,最后得到树的最小表示hash值。复杂度nlogn。

    快速的算法可以参考 <Hash在信息学竞赛中的一类应用-杨弋>。

    无根树可以通过一次拓扑排序,将整棵树收缩,最后只剩下一个点或者是两个点。枚举根即可。

    贴一下UVA 12489 - Combating cancer 的代码,一脸水过的样子,不知道为什么用度序列hash连样例都过不了,01序列hash就过了。

    hash函数找CJboy要的一个字符串hash的函数,不明觉厉~~

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<iostream>
    
    using namespace std;
    
    #define For(i,forN) for(int i=0;i<forN;i++)
    #define ForEdge(i,u) for(int i=head[u];i!=-1;i=edge[i].next)
    #define sf  scanf
    #define pf  printf
    #define mp  make_pair
    
    #define _clr(x,y)   memset(x,(y),sizeof(x))
    
    typedef unsigned int UI ;
    const int Maxn=21000,Mod=2081,hx=557,hy=131;
    /*
        判断树的同构,用此hash函数:
    */
    int head[Maxn],etot,Cc[Maxn];
    int n;
    UI  Hash[Maxn];
    bool vis[Maxn];
    
    struct Edge
    {
        int to,next;
    }edge[Maxn*2];
    
    void init_edge()
    {
        etot=0;
        _clr(head,-1);
    }
    
    void add_edge(int u,int v)
    {
        edge[etot].to=v;
        edge[etot].next=head[u];
        head[u]=etot++;
    }
    
    void dfs(int u)
    {
        vis[u]=true;
        vector < int > Ve;
        ForEdge(i,u)
        {
            int v=edge[i].to;
            if(!vis[v])
            {
                dfs(v);
                Ve.push_back(Hash[v]);
            }
        }
        sort(Ve.begin(),Ve.end());  Ve.push_back(1);//可以看做字符')',或者1
        UI b = 378551 , a = 63689;
        Hash[u]=0;//可以看做字符'(',或者0
        For(i,Ve.size())
        {
            Hash[u]=Hash[u]*a+Ve[i];
            a*=b;
        }
        Hash[u]&=0x7FFFFFFF;
    }
    
    int din[Maxn],stk[Maxn],top;
    int ans[2][2];
    
    int main()
    {
        while(~sf("%d",&n))
        {
            int tid[2]={0};
            for(int cas=0;cas<2;cas++)
            {
                init_edge();
                int u,v;
                queue < int > q;
                _clr(din,0);
                for(int i=1;i<n;i++)
                {
                    sf("%d%d",&u,&v);
                    din[u]++,din[v]++;
                    add_edge(u,v);
                    add_edge(v,u);
                }
                int last=n;
                _clr(vis,false);
                for(int i=1;i<n+1;i++)
                {
                    if(din[i]==1)   q.push(i),last--,vis[i]=true;
                }
                while(last!=0 && !q.empty())
                {
                    u=q.front();    q.pop();    din[u]--;
                    ForEdge(i,u)
                    {
                        int v=edge[i].to;
                        if(!vis[v])
                        {
                            din[v]--;
                            if(din[v]==1)
                            q.push(v),last--,vis[v]=true;
                        }
                    }
                }
                for(int i=1;i<=n;i++)
                {
                    if(din[i]==1)
                    {
                        _clr(vis,false);    dfs(i);
                        ans[cas][tid[cas]++]=Hash[i];
                        if(tid[cas]>2)  while(1);
                    }
                }
            }
            bool flag=false;
            for(int i=0;i<tid[0];i++)
            for(int j=0;j<tid[1];j++)
            if(ans[0][i] == ans[1][j])
            flag=true;
            if(flag)    puts("S");
            else    puts("N");
        }
        return 0;
    }
  • 相关阅读:
    独木舟上的旅行
    会场安排问题
    喷水装置(二)
    喷水装置(一)
    款待奶牛
    整理书本
    贪心算法基本思想和典型例题(转)
    贪心算法
    太乱了,不要了
    Runtime Error:Floating point exception 不知道拿错了
  • 原文地址:https://www.cnblogs.com/CooCoo/p/3406186.html
Copyright © 2011-2022 走看看