Closest Common Ancestors

Write a program that takes as input a rooted tree and a list of pairs of vertices. For each pair (u,v) the program determines the closest common ancestor of u and v in the tree. The closest common ancestor of two nodes u and v is the node w that is an ancestor of both u and v and has the greatest depth in the tree. A node can be its own ancestor (for example in Figure 1 the ancestors of node 2 are 2 and 5)

Input

The data set, which is read from a the std input, starts with the tree description, in the form:

nr_of_vertices
vertex:(nr_of_successors) successor1 successor2 ... successorn
...
where vertices are represented as integers from 1 to n ( n <= 900 ). The tree description is followed by a list of pairs of vertices, in the form:
nr_of_pairs
(u v) (x y) ...

The input file contents several data sets (at least one).
Note that white-spaces (tabs, spaces and line breaks) can be used freely in the input.

Output

For each common ancestor the program prints the ancestor and the number of pair for which it is an ancestor. The results are printed on the standard output on separate lines, in to the ascending order of the vertices, in the format: ancestor:times
For example, for the following tree:

Sample Input

5
5:(3) 1 4 2
1:(0)
4:(0)
2:(1) 3
3:(0)
6
(1 5) (1 4) (4 2)
      (2 3)
(1 3) (4 3)

Sample Output

2:1
5:5

Hint

Huge input, scanf is recommended.
题意:求最近公共祖先,模板题。
  1 #include <iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<queue>
  6 #include<map>
  7 #include<algorithm>
  8 typedef long long ll;
  9 using namespace std;
 10 const int MAXN=1e3+10;
 11 int m,n;
 12 int visit[MAXN];
 13 int is_root[MAXN];
 14 int str[MAXN];
 15 int head[MAXN];//以第i条边为起点的最后输入的那个编号
 16 int ans[MAXN];
 17 int mp[MAXN][MAXN];
 18 int cnt,root,x,y,cx,cy;
 19 struct node
 20 {
 21     int to;//边的终点
 22     int next;//与第i条边同起点的一条边的存储位置
 23     int vi;//权值
 24 }edge[MAXN];
 25 void add_edge(int x,int y)
 26 {
 27     edge[cnt].to=y;
 28     edge[cnt].next=head[x];
 29     head[x]=cnt++;
 30 }
 31 void init()
 32 {
 33     cnt=1;
 34     memset(visit,0,sizeof(visit));
 35     memset(mp,0,sizeof(mp));
 36     memset(ans,0,sizeof(ans));
 37     memset(is_root,true,sizeof(is_root));
 38     memset(head,-1,sizeof(head));
 39     for(int i=1;i<=m;i++)
 40     {
 41         str[i]=i;
 42     }
 43     int p,k;
 44     for(int i=1;i<=m;i++)
 45     {
 46         scanf("%d:(%d)",&p,&k);
 47         for(int j=1;j<=k;j++)
 48         {
 49          scanf("%d",&x);
 50          add_edge(p,x);
 51          is_root[x]=false;
 52         }
 53 
 54     }
 55     for(int i=1;i<=m;i++)//找根节点(入度为0的点)
 56     {
 57         if(is_root[i])
 58         {
 59             root=i;
 60             break;
 61         }
 62     }
 63 }
 64 int Find(int x)
 65 {
 66     int temp=x;
 67     while(temp!=str[temp])
 68     {
 69         temp=str[temp];
 70     }
 71     return temp;
 72 }
 73 void Unit(int x,int y)
 74 {
 75     int root1=Find(x);
 76     int root2=Find(y);
 77     if(root1!=root2)
 78     {
 79         str[y]=root1;
 80     }
 81 }
 82 void LCA(int u)
 83 {
 84     for(int i=head[u];i!=-1;i=edge[i].next)
 85     {
 86         int v=edge[i].to;
 87         LCA(v);
 88         Unit(u,v);
 89         visit[v]=true;
 90     }
 91     for(int i=1;i<=m;i++)//遍历图中所有点,找出与当前顶点u有关系的点,若该点i已访问,则找到v,i的lca;
 92     {
 93         if(visit[i]&&mp[u][i])
 94         {
 95             int k=Find(i);
 96             ans[k]+=mp[u][i];
 97         }
 98     }
 99 }
100 void solve()
101 {
102     scanf("%d",&n);
103     for(int i=1;i<=n;i++)
104     {
105         scanf(" (%d%d)",&cx,&cy);
106         mp[cx][cy]++;
107         mp[cy][cx]++;
108     }
109     LCA(root);
110 }
111 void output()
112 {
113     for(int i=1;i<=m;i++)
114     {
115         if(ans[i])
116         {
117             printf("%d:%d\n",i,ans[i]);
118         }
119     }
120 }
121 int main()
122 {
123     while(scanf("%d",&m)!=-1)
124     {
125         init();
126         solve();
127         output();
128     }
129     return 0;
130 }

 

posted @ 2018-08-04 09:52  左手边五十米  阅读(238)  评论(0编辑  收藏  举报