zoukankan      html  css  js  c++  java
  • HDU 4409 Family Name List --乱搞、LCA

    题意: 给出一些名字,名字间有父子关系,有三种操作:

    1.按祖先到后代,兄弟间按字典序由小到大排序,然后输出

    2.求某个节点的兄弟节点有多少个,包括自己(注意,根节点的兄弟节点是1)

    3.求节点a和b的公共祖先 (注意:如果公共祖先是a或b,必须要输出其父亲,与传统的LCA可以是自己不同)

    解法: 先把整棵树整理出来,son[u]表示u的儿子个数,用来求兄弟个数, fa[u]表示父亲,Gson存储儿子的标号,关于排序的问题,先读入所有名字,然后排个序哈希一下,使字典序小的节点标号一定小,那么直接sort(Gson.begin(),Gson.end()) 就将儿子排序了。

    然后用RMQ 搞在线LCA 即可

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <string>
    #include <vector>
    #include <map>
    using namespace std;
    #define N 30107
    
    map<string,int> mp;
    int son[N],fa[N],cnt[N];
    vector<int> Gson[N];
    string TS[N],NS[N];
    int ati[60004],f[60006],bn,b[90008],dp[60005][32],ind;
    
    void dfs(int u,int dep)
    {
        for(int i=0;i<dep;i++) printf(".");
        cout<<NS[u]<<endl;
        for(int i=0;i<Gson[u].size();i++)
        {
            int v = Gson[u][i];
            dfs(v,dep+1);
        }
    }
    
    void init()
    {
        memset(ati,0,sizeof(ati));
        memset(f,0,sizeof(f));
        memset(b,0,sizeof(b));
        memset(dp,0,sizeof(dp));
        bn = ind = 0;
    }
    
    void dfs_2(int u,int father)
    {
        int tmp = ++ind;
        f[tmp] = u;
        b[++bn] = tmp;
        ati[u] = bn;
        for(int i=0;i<Gson[u].size();i++)
        {
            int v = Gson[u][i];
            if(v==father) continue;
            dfs_2(v,u);
            b[++bn]=tmp;
        }
    }
    
    void RMQ_init(int n)
    {
        for (int i=1; i<=n; i++)  dp[i][0]=b[i];
        int m=floor(log((double)n*1.0)/log((double)2.0));
        for (int j=1; j<=m; j++)
          for (int i=1; i<=n-(1<<j)+1; i++)
              dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    }
    
    int RMQ(int l,int r)
    {
        int k=floor(log((double)r-l+1)/log(2.0));
        return min(dp[l][k],dp[r-(1<<k)+1][k]);
    }
    
    int LCA(int a,int b)
    {
        if (ati[a] > ati[b]) swap(a,b);
        return f[RMQ(ati[a],ati[b])];
    }
    
    int main()
    {
        int n,m,i,j;
        while(scanf("%d",&n)!=EOF && n)
        {
            mp.clear();
            memset(son,0,sizeof(son));
            memset(fa,0,sizeof(fa));
            string ss;
            for(i=0;i<=n;i++) Gson[i].clear();
            for(i=1;i<=n;i++)
            {
                cin>>TS[i];
                int len = TS[i].length();
                for(j=0;j<len;j++)
                    if(TS[i][j] != '.') break;
                NS[i] = TS[i].substr(j,len-j);
            }
            sort(NS+1,NS+n+1);
            for(i=1;i<=n;i++)
                mp[NS[i]] = i;
            for(i=1;i<=n;i++)
            {
                ss = TS[i];
                int len = ss.length();
                for(j=0;j<len;j++)
                    if(ss[j] != '.') break;
                string S = ss.substr(j,len-j);
                cnt[j] = mp[S]; 
                if(j != 0)
                {
                    fa[mp[S]] = cnt[j-1];  //最近的有j-1个'.'的名字就是有j个'.'的名字的父亲
                    son[cnt[j-1]]++;
                    Gson[cnt[j-1]].push_back(mp[S]);
                }
                else
                    fa[mp[S]] = 0;
            }
            for(i=1;i<=n;i++)
                sort(Gson[i].begin(),Gson[i].end());
            for(i=1;i<=n;i++)
                if(fa[i] == 0) break;
            int father = i;
            init();
            dfs_2(father,0);
            RMQ_init(bn);
            scanf("%d",&m);
            char s[5];
            while(m--)
            {
                scanf("%s",s);
                if(s[0] == 'L')
                    dfs(father,0);
                else if(s[0] == 'b')
                {
                    cin>>ss;
                    int k = mp[ss];
                    if(k == father) puts("1");
                    else printf("%d
    ",son[fa[k]]);
                }
                else
                {
                    string S1,S2;
                    cin>>S1>>S2;
                    int ms1 = mp[S1];
                    int ms2 = mp[S2];
                    int fat = LCA(ms1,ms2);
                    if(fat == ms1 || fat == ms2)  cout<<NS[fa[fat]]<<endl;
                    else                          cout<<NS[fat]<<endl;
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    20162302预备作业02
    20162302预备作业01
    设计模式第二次作业
    设计模式第一次作业
    项目选题报告(团队)
    高级软件工程结对第二次作业
    高级软件工程团队第一次作业
    高级软件工程结对第一次作业
    高级软件工程第二次作业
    高级软件工程第一次作业--准备
  • 原文地址:https://www.cnblogs.com/whatbeg/p/4086073.html
Copyright © 2011-2022 走看看