题意给出一颗树, 后给出m 组(u,v)查询;找到每组两个节点的最近公共祖先, 后按祖先数从小到大输出,最近公共祖先 和以其为祖先的数量
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int M = 1000;
vector<int>que[M];
int sign[M][M];
int Set[M];
int num[M];
int vist[M];
int rd[M];
int n, m;
void init() {
memset(sign, 0, sizeof(sign));
for(int i = 0; i < M; i++){
//Set[i] = i;
num[i] = 0;
vist[i] = 0;
rd[i] = 0;
que[i].clear();
}
}
int Find(int x) {
return x == Set[x] ? x : Set[x] = Find(Set[x]);
}
void LCA(int u) {
int v;
Set[u] = u;
for(int i = 0; i < (int)que[u].size(); i++){
v = que[u][i];
LCA(v);
Set[v] = u;
}
vist[u] = 1;
for(int i = 1; i <= n; i++){
if(vist[i] && sign[u][i]){
num[Find(i)] += sign[u][i];
}
}
}
int main()
{
int a, b, c;
while(scanf("%d", &n) != EOF) {
init();
for(int i = 0; i < n; i++){
scanf("%d:(%d)", &a, &b);
for(int j = 0; j < b; j++){
scanf("%d", &c);
que[a].push_back(c);
rd[c]++;
}
}
scanf("%d", &m);
for(int i = 0; i < m; i++){
scanf(" (%d%d)", &a, &b); //正确输入;
//scanf("(%d%d)", &a, &b); //这种输入将得不到结果;因为双引号后没有空格;
sign[a][b]++;
sign[b][a]++;
}
for(int i = 1; i <= n; i++){
if(rd[i] == 0){
LCA(i);
break;
}
}
for(int i= 1; i <= n; i++){
if(num[i])
printf("%d:%d\n", i, num[i]);
}
}
return 0;
}