HDU 4409 Family Name List(LCA)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4409

题意:给定一个家谱。有三种询问:

(1)L重新打印家谱,同一代的人按照升序;

(2)b name  输出name的亲兄弟有多少个?

(3)c name1 name2输出name1和name2 的最近公共祖先。

注意(3):如果最近公共祖先是name1或者name2,那么要输出其父亲。(因为自己不能是自己的祖先。。)

 

思路:建图的时候就按照正常的建,但是输出的时候将同一个父亲的孩子排序输出(2)在DFS的时候顺便统计一下;(3)就是LCA。

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

using namespace std;





const int MAX=30005;  //节点数量

struct node

{

    int v,next;

};



struct Node

{

    char s[65];

    int id;

};



int cmp(Node a,Node b)

{

    return strcmp(a.s,b.s)<0;

}





node edges[MAX<<1];

int head[MAX],e;

int pre[MAX],dep[MAX];

int id[MAX]; //节点第一次被遍历的顺序

int RMQ[MAX*3][20];

int curID;

//F[i]表示第i个遍历的节点

//B[i]表示F[i]在树中的深度

int F[MAX*3],B[MAX*3];



int father[MAX],d[MAX];

int ID;

Node hash[MAX],hash1[MAX];



int add(char str[])

{

    ID++;

    strcpy(hash[ID].s,str);

    hash[ID].id=ID;

    return ID;

}



int getID(char str[])

{

    int low=1,high=ID,mid;

    while(low<=high)

    {

        mid=(low+high)>>1;

        if(strcmp(hash[mid].s,str)==0) break;

        if(strcmp(hash[mid].s,str)<0) low=mid+1;

        else high=mid-1;

    }

    return hash[mid].id;

}



void init()

{

    curID=0;

    ID=0;

    memset(head,-1,sizeof(head));

    e=0;

}



void Add(int u,int v)

{

    edges[e].v=v;

    edges[e].next=head[u];

    head[u]=e++;

}



int sonNum[MAX];



void DFS(int u,int p,int Dep)

{

    int i,v;

    

    curID++;

    F[curID]=u;  B[curID]=Dep;

    id[u]=curID; pre[u]=p; dep[u]=Dep;

    

    sonNum[u]=0;

    for(i=head[u];i!=-1;i=edges[i].next)

    {

        v=edges[i].v;

        if(v==p) continue;

        DFS(v,u,Dep+1);

        curID++;

        F[curID]=u;

        B[curID]=Dep;

        sonNum[u]++;

    }

}



void initRMQ()

{

    int i,j,x,y;

    for(i=1;i<=curID;i++) RMQ[i][0]=i;

    for(j=1;(1<<j)<=curID;j++) for(i=1;i+(1<<j)-1<=curID;i++)

    {

        x=RMQ[i][j-1];

        y=RMQ[i+(1<<(j-1))][j-1];

        RMQ[i][j]=B[x]<B[y]?x:y;

    }

}



int getLCA(int a,int b)

{

    int k,x,y;

    a=id[a];b=id[b];

    if(a>b) k=a,a=b,b=k;

    k=log(1.0+b-a)/log(2.0);

    x=RMQ[a][k];

    y=RMQ[b-(1<<k)+1][k];

    return B[x]<B[y]?F[x]:F[y];

}



void build(int n)

{

    char str[65];

    int i,j,k,u,v;

    

    scanf("%s",str);

    u=add(str);

    d[u]=0;father[u]=-1;

    for(i=2;i<=n;i++)

    {

        scanf("%s",str);

        for(j=0;str[j]=='.';j++);

        for(k=j;str[k];k++) str[k-j]=str[k];

        str[k-j]='\0';

        v=add(str);

        d[v]=j;

        while(d[u]+1!=d[v]) u=father[u];

        Add(u,v);

        father[v]=u;

        u=v;

    }

}



int temp[MAX],start[MAX],size[MAX];

void print(int u,int dep)

{

    int i,j,v;

    for(i=1;i<=dep;i++) putchar('.');

    printf("%s\n",hash1[u].s);

    for(i=start[u];i<start[u]+size[u];i++)

    {

        j=temp[i];

        v=edges[j].v;

        print(v,dep+1);

    }

}





int cmp1(int a,int b)

{

    int v1=edges[a].v;

    int v2=edges[b].v;

    return strcmp(hash1[v1].s,hash1[v2].s)<0;

}



void deal(int Q)

{

    char cmd[5],str[65],str1[65];

    int i,j,u,v;

    for(i=1;i<=ID;i++) hash1[i]=hash[i];

    sort(hash+1,hash+ID+1,cmp);

    u=1;

    for(i=1;i<=ID;i++)

    {

        size[i]=0;

        start[i]=u;

        for(j=head[i];j!=-1;j=edges[j].next)

        {

            temp[u]=j;

            size[i]++;

            u++;

        }

        if(size[i])

        {

            sort(temp+start[i],temp+start[i]+size[i],cmp1);

        }

    }

    while(Q--)

    {

        scanf("%s",cmd);

        if(cmd[0]=='L')

        {

            print(1,0);

        }

        else if(cmd[0]=='b')

        {

            scanf("%s",str);

            u=getID(str);

            if(father[u]==-1) puts("1");

            else printf("%d\n",sonNum[father[u]]);

        }

        else if(cmd[0]=='c')

        {

            scanf("%s%s",str,str1);

            u=getID(str);

            v=getID(str1);

            i=getLCA(u,v);

            if(i==u||i==v) i=father[i];

            printf("%s\n",hash1[i].s);

        }

    }

}









int n,Q;



int main()

{

    while(scanf("%d",&n),n)

    {

        init();

        build(n);

        DFS(1,0,0);

        initRMQ();

        scanf("%d",&Q);

        deal(Q);

    }

    return 0;

}

  

 

 

你可能感兴趣的:(list)