当前位置: 代码迷 >> 综合 >> POJ 1470 Closest Common Ancestors
  详细解决方案

POJ 1470 Closest Common Ancestors

热度:25   发布时间:2023-12-06 08:52:30.0

题目描述:点击打开链接


题目大意:

给定一棵树和一些询问,求每个询问的LCA,打印每个节点在询问中是LCA的次数。

输入的第一行是结点个数n,接下来的n行中,第一个数是描述的节点,括号中是该节点的儿子的个数,在后面的数是该节点的儿子。然后是一个数m,代表询问的个数,后面是形如(x,y)的询问,就是问x和y的LCA。

输出是 节点:次数 的格式,是每个节点是LCA的次数。


这题就是用tarjan算法求LCA。

我犯了这些错误:

1、询问可能会重复,所以在记录时要记录它的出现次数。

2、输入时随心所欲的空格让我错了很久,在网上看了题解,借用了一下输入方法。然后就因输入时多加了一个getchar()让我WA了一个小时。


代码:

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;int n,m;
vector<int> a[905];
int que[905][905]= {0};int fa[905]= {0};
int find(int x) {if(fa[x]==0) {return x;}return fa[x]=find(fa[x]);
}int use[905]= {0};
int ans[905]= {0};
void lca(int x) {for(int i=0; i<a[x].size(); i++) {lca(a[x][i]);fa[a[x][i]]=x;}use[x]=true;for(int i=1; i<=n; i++) {if(use[i]&&que[x][i]) {ans[find(i)]+=que[x][i];}}return ;
}int main() {while(scanf("%d",&n)!=EOF) {memset(fa,0,sizeof(fa));memset(use,0,sizeof(use));memset(que,0,sizeof(que));memset(ans,0,sizeof(ans));for(int i=1; i<=n; i++) {a[i].clear();}bool root[905]= {0};for(int i=1; i<=n; i++) {int x,y;scanf("%d:(%d)",&x,&y);for(int j=1; j<=y; j++) {int z;scanf("%d",&z);a[x].push_back(z);root[z]=true;}}scanf("%d",&m);for(int i=1; i<=m; i++) {int x,y;char xx;scanf(" (%d %d)",&x,&y);que[x][y]++,que[y][x]++;}for(int i=1; i<=n; i++) {if(root[i]==false) {lca(i);break;}}for(int i=1; i<=n; i++) {if(ans[i]) {printf("%d:%d\n",i,ans[i]);}}}return 0;
}


  相关解决方案