POJ 1470/PKU 1470 Closest Common Ancestors __LCA

题目链接: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;

}


 

 

你可能感兴趣的:(close)