Closest Common
Ancestors
Description
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
题意: 找出最近的公共祖先.
解题思路:
1. 这题有个陷阱, 同一对点可能多次访问.
2. 数组链表改成用STL + tarjan算法. AC了~~~
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
#define MAX 1005
struct node
{
int v;
};
vector<node> edges[MAX],
qu[MAX];
int n, m;
bool flag[MAX], vis[MAX];
int p[MAX], num;
int du[MAX], start;
int result[MAX];
int find(int x)
{
return x == p[x] ? x : (p[x] =
find(p[x]));
}
void read_graph()
{
memset(flag,false,sizeof(flag));
memset(vis,false,sizeof(vis));
memset(du,0,sizeof(du));
memset(result,0,sizeof(result));
int u, v;
int temp, i;
node t;
for(i = 1; i <= n; ++i)
{
qu[i].clear();
edges[i].clear();
}
for(i = 1; i <= n; ++i)
{
scanf("%d:(%d)",&u,&temp);
for(int j = 0; j
< temp; ++j)
{
scanf("%d",&v);
du[v]++;
t.v =
v;
edges[u].push_back(t);
}
}
char ch;
scanf("%d",&m);
for(i = 1; i <= m; ++i)
{
while(scanf("%c",&ch)
&& ch != '(');
scanf("%d
%d",&u,&v);
while(scanf("%c",&ch)
&& ch != ')');
t.v = v;
qu[u].push_back(t);
t.v = u;
qu[v].push_back(t);
}
for(i = 1; i <= n; ++i)
{
if(du[i] == 0)
{
start =
i;
break;
}
}
}
void LCA(int x)
{
int v, e, i, t;
vis[x] = true;
p[x] = x;
t = edges[x].size();
for(i = 0; i < t; ++i)
{
v = edges[x][i].v;
if( !vis[v] )
{
LCA(v);
p[v] =
x;
}
}
flag[x] = true;
t = qu[x].size();
for(i = 0; i < t; ++i)
{
v = qu[x][i].v;
if(flag[v])
{
e =
find(v);
result[e]++;
}
}
}
int main()
{
// freopen("input.txt","r",stdin);
while(scanf("%d",&n) !=
EOF)
{
read_graph();
LCA(start);
for(int i = 1; i
<= n; ++i)
{
if(result[i]
!= 0)
{
printf("%d:%d\n",i,result[i]);
}
}
}
return 0;
}