hdu1470Closest Common Ancestors LCA

来源:互联网 发布:管家婆数据库 编辑:程序博客网 时间:2024/06/07 18:53
//刚学lca,代码是参考大神的
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1010;
const int maxq=500010;
int parent[maxn];
int ancestor[maxn];
int answer[maxq];
//**********************//并查集的函数
int find(int i)
{
    if(parent[i]==-1)return i;
    return parent[i]=find(parent[i]);
}
int join(int x,int y)
{
    int x1=find(x);
    int y1=find(y);
    if(x1!=y1)
    parent[y1]=x1;
}
//**********************//存入数的边的邻接表
int vis[maxn];
int head[maxn];
int nedge;
struct Edge
{
    int to, next;
}edge[2*maxn];
void addedge(int u,int v)
{
    edge[nedge].to=v;
    edge[nedge].next=head[u];
    head[u]=nedge++;
}
//****************************//存入询问的边的邻接表
struct Query
{
    int to,next,id;
}query[2*maxq];
int nquery;
int h[maxq];
void addquery(int u,int v,int w)
{
    query[nquery].to=v;
    query[nquery].id=w;
    query[nquery].next=h[u];
    h[u]=nquery++;
}
//******************************//初始化
void init()
{
    nedge = nquery = 0;
    memset(parent,-1,sizeof(parent));
    memset(head,-1,sizeof(head));
    memset(h,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(ancestor,0,sizeof(ancestor));
}
//*************************************
int temp;
void  tarjan(int u)
{
    ancestor[u]=u;
    vis[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(vis[v])continue;
        tarjan(v); 
        join(u,v);      //合并v到父节点u的集合,确保集合的祖先是u               
        ancestor[find(v)]=u;          
    }
    for(int i = h[u];i!=-1;i=query[i].next)//处理完一个以u为根节点的子树后,这个子树的所有节点都是在一个集合中
    {                                     //而且它们的祖先都是u
        int v=query[i].to;                //而对于询问中与u节点相连的节点v,
        if(vis[v])                         //如果在这个子树中,那么他们的公共祖先就是u,如果不是,而且在之前
        answer[query[i].id]=ancestor[find(v)];//搜索过那么是原来节点所在集合的祖先
    }
}
//******************************************
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,m;
    while(scanf("%d",&n)!=EOF)
    {
        int num;int u;int v;int Q;
        int i,j;
        int flag[maxn];
        init();
        memset(flag,0,sizeof(flag));
        for(i=1;i<=n;i++)
        {
            scanf("%d:(%d)",&u,&num);
            while(num--)
            {
                scanf("%d",&v);
                addedge(u,v);
                //addedge(v,u);
                flag[v]=1;
            }
         }
           scanf("%d",&Q);
           int a,b;
           char ch;
           for(j=0;j<Q;j++)
           {
               while(getchar()!='(');
               scanf("%d %d)",&a,&b);
               addquery(a,b,j);
               addquery(b,a,j);
           }
        int root;
        for(i=1;i<=n;i++)
        if(!flag[i])
        {
            root=i;
            break;
        }
        tarjan(root);
        int count[maxn];
        memset(count,0,sizeof(count));
        for(i=0;i<Q;i++)
        count[answer[i]]++;
        for(i=1;i<=n;i++)
        if(count[i])
        printf("%d:%d\n",i,count[i]);
    }
}





































0 0
原创粉丝点击