LCA Tarjan算法笔记

参考 https://comzyh.com/blog/archives/492/
Tarjan算法 利用离线的方法求 LCA 复杂度o(n+2q) (离线来做复杂度还是很可观的

查询两点距离的功能之后在补上吧

#include<cstdio>
#include<cstring>
using namespace std;

const int MAXN=1e5+5;
struct node{int to,cost,next;};struct NODE{int to,next;};
NODE que[MAXN<<1];node dat[MAXN<<1];int pit[MAXN],p[MAXN],par[MAXN],vis[MAXN],LCA[MAXN],u,o;

inline void add_edge(int x,int y,int cost){
    dat[u]=(node){y,cost,pit[x]};pit[x]=u++;
    dat[u]=(node){x,cost,pit[y]};pit[y]=u++;
}
inline void add_edge(int x,int y){
    que[o]=(NODE){y,p[x]};p[x]=o++;
    que[o]=(NODE){x,p[y]};p[y]=o++;
}
/*** 以下为主要部分 **/
inline void init(int n){for(int i=0;i<=n;i++) par[i]=i;}
int find(int x){return x==par[x]?x:par[x]=find(par[x]);}
void lca(int v){
    vis[v]=true;
    for(int i=p[v];i;i=que[i].next){
        NODE &e=que[i];
        if(vis[e.to]){
            LCA[(i+1)>>1]=find(e.to);
        }
    }
    for(int i=pit[v];i;i=dat[i].next){
        node &e=dat[i];
        if(vis[e.to]) continue;
        lca(e.to);
        par[e.to]=v;
    }
}

int main()
{
    int V,E,Q;
    while(scanf("%d%d%d",&V,&E,&Q)!=EOF){
        init(V);
        memset(pit,0,sizeof(pit));  u=1;
        memset(p,0,sizeof(p));      o=1;
        for(int i=0;i<E;i++){
            int x,y,cost;
            scanf("%d%d%d",&x,&y,&cost);
            add_edge(x,y,cost);
        }
        for(int i=0;i<Q;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add_edge(x,y);
        }
        lca(1);
        for(int i=1;i<o;i+=2){
            printf("%d & %d -> %d\n",que[i].to,que[i+1].to,LCA[(i+1)/2]);
        }
    }
    return 0;
}
/*
8 7 5
1 2 2
2 3 4
2 4 5
4 5 6
1 6 7
6 7 4
7 8 4
3 4
3 5
5 6
6 7
1 8
  */
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值