标签:
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 26612 | Accepted: 13734 |
Description
Input
Output
Sample Input
2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5
Sample Output
4
3
思路
最近公共祖先模板题
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 10005;
struct Edge{
int to,next;
}edge[maxn];
vector<int>qry[maxn];
int N,tot,fa[maxn],head[maxn],indegree[maxn],ancestor[maxn];
bool vis[maxn];
void init()
{
tot = 0;
for (int i = 1;i <= N;i++) fa[i] = i,head[i] = -1,indegree[i] = 0,vis[i] = false,qry[i].clear();
}
void addedge(int u,int to)
{
edge[tot] = (Edge){to,head[u]};
head[u] = tot++;
}
int find(int x)
{
int r = x;
while (r != fa[r]) r = fa[r];
int i = x,j;
while (i != r)
{
j = fa[i];
fa[i] = r;
i = j;
}
return r;
}
void Union(int x,int y)
{
x = find(x),y = find(y);
if (x == y) return;
fa[y] = x; //不能写成fa[x] = y,与集合合并的祖先有关系
}
void targin_LCA(int u)
{
ancestor[u] = u;
for (int i = head[u];i != -1;i = edge[i].next)
{
int v = edge[i].to;
targin_LCA(v);
Union(u,v);
ancestor[find(u)] = u;
}
vis[u] = true;
int size = qry[u].size();
for (int i = 0;i < size;i++)
{
if (vis[qry[u][i]]) printf("%d\n",ancestor[find(qry[u][i])]);
return;
}
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int u,v;
scanf("%d",&N);
init();
for (int i = 1;i < N;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
indegree[v]++;
}
scanf("%d%d",&u,&v);
qry[u].push_back(v),qry[v].push_back(u);
for (int i = 1;i <= N;i++)
{
if (!indegree[i])
{
targin_LCA(i);
break;
}
}
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
const int MAXN=10010;
int F[MAXN];//并查集
int r[MAXN];//并查集中集合的个数
bool vis[MAXN];//访问标记
int ancestor[MAXN];//祖先
struct Node
{
int to,next;
}edge[MAXN*2];
int head[MAXN];
int tol;
void addedge(int a,int b)
{
edge[tol].to=b;
edge[tol].next=head[a];
head[a]=tol++;
edge[tol].to=a;
edge[tol].next=head[b];
head[b]=tol++;
}
struct Query
{
int q,next;
int index;//查询编号
}query[MAXN*2];//查询数
int answer[MAXN*2];//查询结果
int cnt;
int h[MAXN];
int tt;
int Q;//查询个数
void add_query(int a,int b,int i)
{
query[tt].q=b;
query[tt].next=h[a];
query[tt].index=i;
h[a]=tt++;
query[tt].q=a;
query[tt].next=h[b];
query[tt].index=i;
h[b]=tt++;
}
void init(int n)
{
for(int i=1;i<=n;i++)
{
F[i]=-1;
r[i]=1;
vis[i]=false;
ancestor[i]=0;
tol=0;
tt=0;
cnt=0;//已经查询到的个数
}
memset(head,-1,sizeof(head));
memset(h,-1,sizeof(h));
}
int find(int x)
{
if(F[x]==-1)return x;
return F[x]=find(F[x]);
}
void Union(int x,int y)//合并
{
int t1=find(x);
int t2=find(y);
if(t1!=t2)
{
if(r[t1]<=r[t2])
{
F[t1]=t2;
r[t2]+=r[t1];
}
else
{
F[t2]=t1;
r[t1]+=r[t2];
}
}
}
void LCA(int u)
{
//if(cnt>=Q)return;//不要加这个
ancestor[u]=u;
vis[u]=true;//这个一定要放在前面
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(vis[v])continue;
LCA(v);
Union(u,v);
ancestor[find(u)]=u;
}
for(int i=h[u];i!=-1;i=query[i].next)
{
int v=query[i].q;
if(vis[v])
{
answer[query[i].index]=ancestor[find(v)];
cnt++;//已经找到的答案数
}
}
}
bool flag[MAXN];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
int N;
int u,v;
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
init(N);
memset(flag,false,sizeof(flag));
for(int i=1;i<N;i++)
{
scanf("%d%d",&u,&v);
flag[v]=true;
addedge(u,v);
}
Q=1;//查询只有一组
scanf("%d%d",&u,&v);
add_query(u,v,0);//增加一组查询
int root;
for(int i=1;i<=N;i++)
if(!flag[i])
{
root=i;
break;
}
LCA(root);
for(int i=0;i<Q;i++)//输出所有答案
printf("%d\n",answer[i]);
}
return 0;
}
POJ 1330 Nearest Common Ancestors
标签:
原文地址:http://www.cnblogs.com/zzy19961112/p/5962151.html