POJ 1470 Closest Common Ancestors 离线LCA

来源:互联网 发布:知乎电影1942精彩片段 编辑:程序博客网 时间:2024/05/16 07:22

题目链接

http://poj.org/problem?id=1470

题意

给定一个树,和q个询问包含两个点u和v,试着求出有哪几个点作为他们的LCA,输出之,并输出次数

思路1

离线LCA模板题,根是指定的。

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<string>#include<queue>#include<stack>#include<set>#include<map>#define ll long longusing namespace std;const int INF = ( 2e9 ) + 2;const ll maxn = 1000;vector<int> g[maxn],g2[maxn];int In[maxn],deep[maxn],pre[maxn];int ans[maxn],f[maxn];bool vis[maxn];void init(int n){    for(int i=1;i<=n;i++)    {        g[i].clear();        g2[i].clear();    }    memset(In,0,sizeof(In));    memset(ans,0,sizeof(ans));    memset(vis,0,sizeof(vis));}int Find(int x){    return f[x]==x?x:f[x]=Find(f[x]);}void dfs(int u) // 生成以u为根结点的子树 {    f[u]=u;    vis[u]=1;    for(int i=0,L=g2[u].size();i<L;i++)     {        int v=g2[u][i];        if(vis[v])              // 查询u和v的LCA         {            ans[Find(v)]++;        }    }    for(int i=0,L=g[u].size();i<L;i++)    {        int v=g[u][i];        if(!vis[v])        {            dfs(v); // 递归生成以v为根的子树             f[v]=u; // 生成完毕后,将v的父亲标记为u         }    }}int main(){    int n,u,v;    while(~scanf("%d",&n))    {        int cnt=0;        init(n);        for(int i=1;i<=n;i++)        {            scanf("%d:(%d)",&u,&cnt);            while(cnt--)            {                scanf("%d",&v);                g[u].push_back(v);                g[v].push_back(u);                In[v]++;            }        }        int pr;        scanf("%d",&pr);        while(pr--)        {            scanf(" (%d %d)",&u,&v);            g2[u].push_back(v);            g2[v].push_back(u);        }        int root;        for(int i=1;i<=n;i++)        if(In[i]==0)root=i;        dfs(root);        for(int i=1;i<=n;i++)        if(ans[i]!=0)        {            printf("%d:%d\n",i,ans[i]);        }    }}

思路2

这种方式也能A。速度和离线一样快。。

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<string>#include<queue>#include<stack>#include<set>#include<map>#define ll long longusing namespace std;const int INF = ( 2e9 ) + 2;const ll maxn = 1000;vector<int> g[maxn];int In[maxn],deep[maxn],pre[maxn];int ans[maxn];void dfs(int u,int fa,int dep){    deep[u]=dep;    for(int i=0,L=g[u].size();i<L;i++)    {        int v=g[u][i];        if(v!=fa)        {            pre[v]=u;            dfs(v,u,dep+1);        }    }}void init(int n){    for(int i=1;i<=n;i++)g[i].clear();    memset(In,0,sizeof(In));    memset(ans,0,sizeof(ans));}void find(int u,int v){    while(u!=v)    {        if(deep[u]>=deep[v])        u=pre[u];        else        v=pre[v];    }    ans[u]++;}int main(){    int n,u,v;    while(~scanf("%d",&n))    {        int cnt=0;        init(n);        for(int i=1;i<=n;i++)        {            scanf("%d:(%d)",&u,&cnt);            while(cnt--)            {                scanf("%d",&v);                g[u].push_back(v);                g[v].push_back(u);                In[v]++;            }        }        int root;        for(int i=1;i<=n;i++)        if(In[i]==0)root=i;        dfs(root,-1,1);        int pr;        scanf("%d",&pr);        while(pr--)        {            scanf(" (%d %d)",&u,&v);            find(u,v);        }        for(int i=1;i<=n;i++)        if(ans[i]!=0)        {            printf("%d:%d\n",i,ans[i]);        }    }}
原创粉丝点击