lca问题 看了黑书指导的伪码写的 LCA(u) { Make-Set(u) ancestor[Find-Set(u)]=u ① 对于u的每一个孩子v { LCA(v) Union(u) ancestor[Find-Set(u)]=u // 上面①已经确定了u的祖先,不明白这里有什么用的 } checked[u]=true 对于每个(u,v)属于P { if checked[v]=true then { 回答u和v的最近公共祖先为 ancestor[Find-Set(v)] } } } #include <cstdio> #include <cstring> #include <vector> using namespace std; #define NODES 1000 vector<int> vec[NODES]; vector<int> qv[NODES]; int ance[NODES]; int check[NODES]; int arr[NODES]; int f[NODES]; int n; int find(int a){ if (f[a] < 0){ return a; } return f[a] = find(f[a]); } void unions(int a, int b){ a = find(a); b = find(b); if (a != b) { f[a] = b; } } void lca(int u) { int v; ance[find(u)] = u; for(int i = 0; i < vec[u].size(); ++i) { v = vec[u][i]; lca(v); unions(v, u); } check[u] = 1; for(int i = 0; i < qv[u].size(); ++i) { v = qv[u][i]; if(check[v]) //printf("ance(%d, %d) is %d/n", u, v, ance[uf.find(v)]); ++arr[ance[find(v)]]; } } int main (){ while(scanf("%d", &n) - EOF) { int u,v,k; int root = -1; for(int i = 0; i <= n; ++i) { vec[i].clear(); qv[i].clear(); check[i] = 0; arr[i] = 0; ance[i] = i; f[i] = -1; } for(int i = 0; i < n; ++i) { scanf("%d:(%d)", &u, &k); for(int j = 0; j < k; ++j) { scanf("%d", &v); vec[u].push_back(v); } } scanf("%d", &k); for(int i = 0; i < k; ++i) { scanf(" (%d %d)", &u, &v); qv[u].push_back(v); if(u!=v)qv[v].push_back(u); // 注意要建立双向的查询,否则可能找不到 } for(int i = 1; i <= n; ++i) { for(int j = 0; j < vec[i].size(); ++j){ check[vec[i][j]]++; } } for(int i = 1; i <= n; ++i) { if(check[i] == 0){ root = i; break; } } memset(check, 0, sizeof(check)); lca(root); for(int i = 1; i <= n; ++i) { if(arr[i]) printf("%d:%d/n", i, arr[i]); } } return 0; }