POJ 1470/PKU 1470 Closest Common Ancestors __LCA

来源:互联网 发布:淘宝免费推广平台 编辑:程序博客网 时间:2024/05/17 23:43

题目链接: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 & indgreeint anst[1010],color[1010];//ansector & color(visit)//int res[400010];//respondint num[1010];vector<int>query[1010];inline void adde(int u,int v){//add edgeedge[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;}


原创粉丝点击