0
点赞
收藏
分享

微信扫一扫

最近共同祖先(lca)

暮晨夜雪 2022-01-20 阅读 69

1.朴素法

d数组记录的是u,v节点到根节点的深度

int lca(int u,int v){
	if(d[u]<d[v]){     //保证u所在的节点比较深
		swap(u,v); 
	}
	while(d[u]!=d[v]){  //让u和v处于同一深度
		u=father[u];
	}
	while(u!=v){       //将u和v同时上调
		u=father[u];
		v=father[v];
	}
	return u;
}

2.离线Tarjan算法 链接

一次性将要计算最近共同祖先的u,v读入,然后dfs的时候处理这些u和v

//不怕别人比你聪明,就怕别人比你聪明还比你努力
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include <set>
#include <stack>
#include <map>
#include<vector>
#define INF 0x3f3f3f3f
 
using namespace std;
const int MAXN = 10005;
vector<int> vec[MAXN];
bool vis[MAXN];
int per[MAXN],head[MAXN],in_num[MAXN];
//in_num统计每个点的入度,为了求根节点,per和并查集中的作用相同,head配合结构体前向星
int cnt,n,m;
 
struct Node
{
    int c,next;
}edge[MAXN];
 
void Init()
{
    cnt = 0;
    memset(in_num,0,sizeof(in_num));
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    for(int i =1;i <= n;i++)
    {
        vec[i].clear();
        per[i] = i;
    }
}
 
void add(int x,int y)
{
    edge[++cnt].next = head[x];
    edge[cnt].c = y;
    head[x] = cnt;
}
 
int Find(int x)
{
    if(per[x] != x)
        per[x] = Find(per[x]);
    return per[x];
}
 
void Union(int x,int y)
{
    x = Find(x);y = Find(y);
    if(x == y)
        return ;
    per[x] = y;
}
 
void Tarjan(int x)
{
    for(int i = head[x];i != -1; i =edge[i].next)
    {
        int v = edge[i].c;
        Tarjan(v);
        Union(v,x);//首先要一直遍历的叶子节点
    }
    vis[x] = 1; // 当这个节点的所有子节点都已经遍历到了,就标记这个节点
    for(int i = 0;i < vec[x].size();i ++)
        if(vis[vec[x][i]])//然后在问题中寻找是否有关于这两个节点都已经标记过的了
            printf("%d 和 %d 的LAC是 %d\n",x,vec[x][i],Find(vec[x][i]));
}
int main()
{
    int x,y;
    scanf("%d%d",&n,&m);
    Init();
    for(int i = 1;i < n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);
        in_num[y] ++;
    }
    for(int i = 0;i < m;i ++)
    {
        scanf("%d%d",&x,&y);
        vec[x].push_back(y);
        vec[y].push_back(x);
    }
    int root;
    for(int i = 1;i <= n;i ++)
        if(in_num[i] == 0)
            root = i;
    Tarjan(root);
}
/**
8 4
1 2
1 3
2 4
2 5
4 7
5 8
3 6
7 8
5 6
5 2
4 6
**/
 
 

3.在线Tarjan

举报

相关推荐

0 条评论