-
E - Closest Common Ancestors
- POJ - 1470
- 如下图所示4和5的最近公共祖先是2,5和3的最近公共祖先是1,2和1的最近公共祖先是1。
1.任选一个点为根节点,从根节点开始。
- 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过。
- 3.若是v还有子节点,返回2,否则下一步。
- 4.合并v到u上。
- 5.寻找与当前点u有询问关系的点v。
- 6.若是v已经被访问过了,则可以确认u和v的最近公共祖先为v被合并到的父亲节点a。
-
#include<stdio.h> #include<string.h> #include<vector> #define M 1007 using namespace std; int g[M][M],in[M],pre[M],cnt[M]; bool vis[M]; vector<int>v[M]; int n,m; void init() { memset(g,0,sizeof(g)); memset(in,0,sizeof(in)); memset(cnt,0,sizeof(cnt)); memset(vis,false,sizeof(vis)); for(int i=1; i<=n; i++) { v[i].clear(); pre[i]=i; } } int fond(int x) { return x==pre[x]?x:pre[x]=fond(pre[x]); } void unin(int x,int y) { int xx=fond(x); int yy=fond(y); pre[xx]=yy; } void dfs(int x) { int len=v[x].size(); for(int i=0; i<len; i++) { dfs(v[x][i]); unin(v[x][i],x); } vis[x] = true; for(int i=1; i<=n; i++) if(vis[i]&&g[x][i]) cnt[fond(i)]+=g[x][i]; } int main() { while(scanf("%d",&n)!=EOF) { init(); int a,b,c,root; for(int i=1; i<=n; i++) { scanf("%d:(%d)",&a,&b); while(b--) { scanf(" %d",&c); v[a].push_back(c); in[c]++; } } scanf(" %d",&m); while(m--) { scanf(" (%d %d)",&a,&b); g[a][b]++; g[b][a]++; } for(int i=1; i<=n; i++) if(!in[i]) { root=i; break; } dfs(root); for(int i=1; i<=n; i++) { if(cnt[i]) printf("%d:%d\n",i,cnt[i]); } } return 0; }
Closest Common Ancestors -LCA模板
最新推荐文章于 2022-03-25 21:45:22 发布