POJ 1470 Closest Common Ancestors

题目描述:点击打开链接


题目大意:

给定一棵树和一些询问,求每个询问的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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值