题意:求某棵树中Lowest Common Ancestor(最小公共祖先)裸题然后套模板
格式: 样例个数t;结点个数n; (n-1条)边edge;第n行为所求 a b;
思路:解lca无非常见三种方式Tarjan,倍增,rmq;这里我暂时使用Tarjan来解
由于是模板题,所以对Tarjan原理适当写一下;
Tarjan作为一种离线的算法,其主要思想是利用 类似并查集的方法求 公共祖先。也可以说不是类似而是将 并查集这个数据结构作为其的组成一部分。然后就是利用dfs深度优先进行遍历,在遍历过程中不断的合并记录祖先结点。同时要对图进行存储所以也涉及三种图的存储方式,这里就采用较为简单的vector邻接表来存储.(即深搜到底然后回溯合并)
具体内容还可以参考 https://www.cnblogs.com/JVxie/p/4854719.html
涉及数据元素以及函数:
void tarjan(int x);
void init();
int find(int x);
int indegree[maxn];//用于标志寻找根结点(入度为0的点)
bool vis[maxn];//访问
int father[maxn];
int n,m,t,ans;
vector<int>v[maxn];
vector<int>p[maxn];
tarjan部分:
void tarjan(int x)
{
int i,j;
//1.递归并合并
for(j=0;j<v[x].size();j++)
{
int s=v[x][j];
tarjan(s);
father[s]=x;
}
//2.标记已访问结点
vis[x]=1;
//3.询问判断
for(j=0;j<p[x].size();j++)
{
int s=p[x][j];
if(vis[s])
{
ans=find(s);
return;
}
}
}
并查集查找路径压缩部分:
int find(int x)
{
if(father[x]!=x)
father[x]=find(father[x]);
return father[x];
}
关于其他部分的初始化:
void init(){
memset(vis,false,sizeof(vis));
memset(val,0,sizeof(val));
memset(indegree,0,sizeof(indegree));
for(int i = 1;i<=n;i++){
v[i].clear();
p[i].clear();
father[i] = i;
}
}
最后总的ac代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=10005;
void tarjan(int x);
void init();
int find(int x);
int indegree[maxn];//用于标志寻找根结点
bool vis[maxn];//访问
int father[maxn];
int n,m,t,ans;
vector<int>v[maxn];
vector<int>p[maxn];
void init();
int main()
{
int i,x,y,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init();
//创建图同时对非根结点进行标记
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
indegree[y]++;
v[x].push_back(y);
}
scanf("%d%d",&x,&y);
p[x].push_back(y);
p[y].push_back(x);
//找到根结点进入tarjian
for(i=1;i<=n;i++)
{
if(!indegree[i])
tarjan(i);
}
printf("%d\n",ans);
}
return 0;
}
void init()
{
memset(vis,0,sizeof(vis));
memset(indegree,0,sizeof(indegree));
for(int i=1;i<=n;i++)
{
father[i]=i;
v[i].clear();
p[i].clear();
}
}
void tarjan(int x)
{
int i,j;
for(j=0;j<v[x].size();j++)
{
int s=v[x][j];
tarjan(s);
father[s]=x;
}
vis[x]=1;
for(j=0;j<p[x].size();j++)
{
int s=p[x][j];
if(vis[s])
{
ans=find(s);
return;
}
}
}
int find(int x)
{
if(father[x]!=x)
father[x]=find(father[x]);
return father[x];
}