LCA/tarjanPOJ1470-Closest Common Ancestors

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCA/tarjanPOJ1470-Closest Common Ancestors相关的知识,希望对你有一定的参考价值。

【题意】

给出一棵树和多组查询,求以每个节点为LCA的查询数有多少?

【错误点】

①读入的时候,注意它的空格是随意的呀!一开始不知道怎么弄,后来看了DISCUSS区大神的话:

询问部分输入:

scanf("%d",&m);
for(int i=0;i<m;i++){
scanf(" (%d %d)",&a,&b);
}

注意scanf(" 这里有一个空格

②多组数据啊!注意这句话:
The input file contents several data sets (at least one).

③痛心疾首!它问的是以每个节点为LCA的查询数,所以查询可以重复,同样的查询可以累计!

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<vector>
  5 using namespace std;
  6 const int MAXN=900+5;
  7 vector<int> E[MAXN];
  8 int query[MAXN][MAXN];
  9 int cnt[MAXN];
 10 int notrt[MAXN],rt;
 11 int ance[MAXN];
 12 int vis[MAXN];
 13 int m;//结点的总个数 
 14 
 15 int find(int u)
 16 {
 17     int r=u;
 18     while (ance[r]!=r) r=ance[r];
 19     int ans=r;
 20     r=u;
 21     while (ance[r]!=r)
 22     {
 23         int tmp=ance[r];
 24         ance[r]=ans;
 25         r=tmp;
 26     }
 27     return ans;
 28 }
 29 
 30 void tarjan(int u)
 31 {
 32     vis[u]=1;
 33     for (int v=1;v<=m;v++)
 34     {
 35         if (!query[u][v]) continue;
 36         if (vis[v])
 37         //被访问过有两种情况:一是祖先靠左的子树中的后代;或者是自己的祖先。两者的LCA均为v所在并查集的根 
 38         {
 39             int LCA=find(v);
 40             cnt[LCA]+=query[u][v];
 41             //注意,允许同样的查询出现多次,并且同样的查询可以累计! 
 42         }
 43     }
 44     
 45     ance[u]=u;
 46     for (int i=0;i<E[u].size();i++)
 47     {
 48         int v=E[u][i];
 49         tarjan(v);
 50         ance[v]=u;
 51     }
 52 }
 53 
 54 void init()
 55 {
 56     memset(query,0,sizeof(query)); 
 57     memset(cnt,0,sizeof(cnt)); 
 58     memset(notrt,0,sizeof(notrt));
 59     memset(vis,0,sizeof(vis));
 60     for (int i=1;i<=m;i++) E[i].clear();
 61     for (int i=0;i<m;i++)
 62     {
 63         int p,T;
 64         scanf("%d:(%d)",&p,&T);
 65         for (int i=0;i<T;i++)
 66         {
 67             int son;
 68             scanf(" %d",&son);
 69             E[p].push_back(son);
 70             notrt[son]++;
 71         }
 72     } 
 73     
 74     int n;
 75     scanf("%d",&n); 
 76     for (int i=0; i<n; i++) 
 77     {
 78         int a,b;
 79         scanf(" (%d %d)",&a,&b);
 80         //注意这里(前面要有一个空格!否则无法过! 
 81         query[a][b]++;
 82         query[b][a]++;
 83     }
 84     
 85     for (int i=1;i<=m;i++) if (!notrt[i])
 86     {
 87         rt=i;
 88         break;
 89     } 
 90 }
 91 
 92 void print()
 93 {
 94     for (int i=1;i<=m;i++)
 95         if (cnt[i]>0)
 96             cout<<i<<:<<cnt[i]<<endl;
 97 }
 98 
 99 int main()
100 {
101     while (~scanf("%d",&m)) 
102     //注意是多组数据 
103     {
104         init();
105         tarjan(rt);
106         print();
107     }
108     return 0;
109 }

 

以上是关于LCA/tarjanPOJ1470-Closest Common Ancestors的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1470 Closest Common Ancestors

POJ 1470 Closest Common Ancestors LCA

POJ 1470 Closest Common Ancestors (模板题)(Tarjan离线)LCA