求 LCA的几种算法的实现方法模板( 例题POJ1330

哎 感博客还是要写的 要不每天都在偷懒QAQ 真的会变渣的啊

离线Tarjan算法的实现模板

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

const int MAXN = 1e5+10;
int f[MAXN], ances[MAXN];
int in[MAXN], vis[MAXN];
vector<int> tree[MAXN];
vector<int> query[MAXN];
int root, n;
int find(int x)
{
    return x==f[x]?x:f[x]=find(f[x]);
}
int unite(int x,int y)
{
    x= find(x), y = find(y);
    if(x != y) f[x] = y;
}
void init()
{
    for(int i = 0; i <= n; i++) {
        vis[i] = false; tree[i].clear();
        query[i].clear(); in[i] = 0;
        f[i] = i;
    }
}
void input_tree()
{
    for(int i = 0; i < n-1; i++) {
        int x, y;
        scanf("%d%d",&x,&y);
        tree[x].push_back(y);
        in[y]++;
    }
    for(int i = 1; i <= n; i++) if(in[i] == 0) root = i;
}
void input_query()
{
    int x, y;
    scanf("%d%d",&x,&y);
    query[x].push_back(y);
    query[y].push_back(x);
}

void tarjan(int u)
{
    for(int i = 0; i < tree[u].size(); i++) {
        int v = tree[u][i];
        tarjan(v);
        unite(u,v);
        ances[find(u)] = u;
    }
    vis[u] = true;
    for(int i = 0; i < query[u].size(); i++) {
        int v = query[u][i];
        if(vis[v]) printf("%d\n",ances[find(v)]);
    }
}
int main()
{
    int T;
    while(~scanf("%d",&T)) {
        while(T--) {
            scanf("%d",&n);
            init(); input_tree(); input_query();
            tarjan(root);
        }
    }
return 0;
}

在线doubly算法

朴素的算法
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 1e5+10;
vector<int> tree[MAXN];
int root, n;
int in[MAXN];
int par[MAXN], depth[MAXN];
void dfs(int v, int p, int d)    //v , p, d 分别代表节点, 节点父节点, 深度
{
    par[v] = p;
    depth[v] = d;
    for(int i = 0; i < tree[v].size(); i++) {
        if(tree[v][i] != p) dfs(tree[v][i], v, d+1);
    }
}
void init()
{
    //预处理出来 par, depth
    dfs(root, -1, 0);
}
int lca_pusu(int u,int v)
{
    while(depth[u] > depth[v]) u = par[u];
    while(depth[v] > depth[u]) v = par[v];
    while(u != v) {
        u = par[u];
        v = par[v];
    }
}
void input_tree()
{
    for(int i = 0; i < n-1; i++) {
        int x, y;
        scanf("%d%d",&x,&y);
        tree[x].push_back(y);
        in[y]++;
    }
    for(int i = 1; i <= n; i++) if(!in[i]) root = i;
}
void input_query()
{
    int x, y;
    scanf("%d%d",&x,&y);
    printf("%d\n",lca_pusu(x,y));
}

int main()
{
    int T;
    while(~scanf("%d",&T)) {
        while(T--) {
            scanf("%d",&n);
            for(int i = 0; i <= n; i++) {
                tree[i].clear();
                in[i] = 0; depth[i] = 0;
                par[i] = 0;
            }
            input_tree();init();
            input_query();
        }
    }

return 0;
}
倍增
这里写代码片

在线RMQ算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值