標籤:style blog color ar for sp div c on
題意:
給出一棵樹的結構。
給出兩個點X和Y,求它倆的LCA。
思路:
只需求兩個點的LCA,用了兩種方法,一種離線tarjan,一種直接搞。
看代碼。
代碼:
方法一:直接搞。
int const maxn = 10005;int T,n,a,b;int fa[maxn];int X,Y;int main(){ cin>>T; while(T--){ scanf("%d",&n); mem(fa,-1); rep(i,1,n-1){ scanf("%d%d",&a,&b); fa[b]=a; } scanf("%d%d",&X,&Y); map<int,char> mp; int t1=X; while(t1!=-1){ mp[t1]=1; t1=fa[t1]; } t1=Y; while(t1!=-1){ if(mp[t1]==1){ printf("%d\n",t1); break; } t1=fa[t1]; } }}
方法二:離線tarjan。
int const maxn = 10005;struct node{ int to,w,next,lca;};node edge[maxn*2];bool vis[maxn];int cnt1,cnt2;int head[maxn], fa[maxn];bool flag;int X,Y,n;inline void Addedge(int u,int v,int w){ edge[++cnt1].w=w; edge[cnt1].to=v; edge[cnt1].next=head[u]; head[u]=cnt1;}void init(){ mem(head,-1); mem(vis,false); cnt1=0; flag=false; rep(i,1,n) fa[i]=i;}int findFa(int x){ if(fa[x]==x) return fa[x]; return fa[x]=findFa(fa[x]);}void Tarjan_LCA(int u){ //離線LCA演算法 if(flag) return; fa[u]=u; vis[u]=true; for(int i=head[u];i!=-1;i=edge[i].next){ if(!vis[edge[i].to]){ Tarjan_LCA(edge[i].to); fa[edge[i].to]=u; } } if(u==Y && !flag){ if(vis[X]){ printf("%d\n",findFa(X)); flag=true; return; } } if(u==X && !flag){ if(vis[Y]){ printf("%d\n",findFa(Y)); flag=true; return; } }}int T,a,b;int main(){ cin>>T; while(T--){ scanf("%d",&n); init(); bool t1[maxn]={0}; rep(i,1,n-1){ scanf("%d%d",&a,&b); Addedge(a,b,1); t1[b]=true; } scanf("%d%d",&X,&Y); rep(i,1,n) if(!t1[i]){ Tarjan_LCA(i); //i為樹的根結點 break; } }}
poj 1330 Nearest Common Ancestors (最簡單的LCA)