现在的位置: 首页 > 综合 > 正文

POJ 1470/PKU 1470 Closest Common Ancestors __LCA

2013年04月27日 ⁄ 综合 ⁄ 共 1806字 ⁄ 字号 评论关闭

题目链接:http://poj.org/problem?id=1470

题目大意:开始让你构造一棵树,然后有Q对u,v,最后让你求出每对u,v的最近祖先的编号和次数。

输入一个Q,然后有Q组(u,v)每组中间还有空格,tab等。但,稍稍想一下就能发现,Q组uv一共有Q*2个字符串,所以我们讲稿Q*2组str就可以了scanf("%s",str),然后处理每组str求得u,v

/*/
/*lca离线算法
/*/

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<ctime>
#include<cmath>
#include<climits>
#define sf scanf
#define pf printf
#define cls(a) memset(a,0,sizeof(a))
#define _cls(a) memset(a,-1,sizeof(a))


using namespace std;

struct Edge_t{
	int to,next;
}edge[3010];
int head[1010],et,qhead[1010],qt;//- -
int root[1010],ind[1010];//union & indgree
int anst[1010],color[1010];//ansector & color(visit)
//int res[400010];//respond
int num[1010];
vector<int>query[1010];

inline void adde(int u,int v){//add edge
	edge[et].to=v,edge[et].next=head[u],head[u]=et++;
}
inline int Find(int x){ return root[x]=root[x]==x?x:Find(root[x]);}

void Union(int u,int v){
	int ra=Find(u),rb=Find(v);
	root[rb]=ra;
}

void LCA(int u){//从根节点开始
	int v,e;
	anst[u]=u;
	for(e=head[u];e!=-1;e=edge[e].next){
		LCA((v=edge[e].to));
		Union(u,v);
		anst[Find(u)]=u;
	}
	color[u]=1;
	int s=query[u].size(),i=0;
	for(;i<s;++i)
		if(color[v=query[u][i]]){
			//res[query[e].pos]=
			num[anst[Find(v)]]++;
		}
}

int deal(char *s,int v){
	int i,ret=0;
	if(v){
		for(i=1;s[i];++i)
			ret*=10,ret+=s[i]-'0';
	}else{
		for(i=0;s[i+1];++i)
			ret*=10,ret+=s[i]-'0';
	}
	//pf("ret=%d\n",ret);
	return ret;
}

int main(){
	int n,m,i;
	int t,u,v;
	while(~sf("%d",&n)){
		for(qt=et=0,i=1;i<=n;++i)
			root[i]=i,head[i]=-1,ind[i]=0,anst[i]=-1,color[i]=0,query[i].clear(),num[i]=0;
		for(i=0;i<n;++i){
			sf("%d:(%d)",&u,&v);
			//pf("u=%d v=%d\n",u,v);
			while(v--){
				sf("%d",&m);
				adde(u,m);
				ind[m]++;
			}
		}
		int Q;
		char str[20];
		sf("%d",&Q);
		Q<<=1;//一共Q*2个字符串
		for(i=0;i<Q;++i){
			sf("%s",str);
			if(i&1) v=deal(str,0),query[u].push_back(v),query[v].push_back(u);
			else u=deal(str,1);//后面那个1表示u,0表示v
		}
		for(i=1;i<=n;++i)
			if(!ind[i]) break;
		LCA(i);
		for(i=1;i<=n;++i)
			if(num[i]) pf("%d:%d\n",i,num[i]);
	}
	return 0;
}

抱歉!评论已关闭.