LCA模板

tarjan:
#define up(i, j, k) for(int i = j; i <= k; ++i)
#define down(i, j, k) for(int i = j; i >= k; --i)
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <map>

using namespace std;

int aim[20000],len[20000],nxt[20000],first[10001];
int _src[2000001],_aim[2000001],_lca[1000001],_nxt[2000001],_first[10001];
int fa[10001],visit[10001],dist[10001];
int tot,n,m,c;

void addedge(int u,int v,int w)
{
    aim[tot]=v; len[tot]=w; nxt[tot]=first[u]; first[u]=tot++;
}

void addask(int u,int v)
{
    _src[tot]=u; _aim[tot]=v; _nxt[tot]=_first[u]; _first[u]=tot++;
}

int find(int v)
{
    return fa[v]==v?v:fa[v]=find(fa[v]);
}

void tarjan(int u,int x)
{
    visit[u]=x;
    fa[u]=u;
    for (int i=first[u];~i;i=nxt[i])
        if (!visit[aim[i]])
        {
            dist[aim[i]]=dist[u]+len[i];
            tarjan(aim[i],x);
            fa[aim[i]]=u;
        }
    for (int i=_first[u];~i;i=_nxt[i])
        if (visit[_aim[i]]==x)
            _lca[i/2]=find(_aim[i]);
}

void init()
{
    memset(first,-1,sizeof(first));
    memset(_first,-1,sizeof(_first));
    memset(visit,0,sizeof(visit));
}

int main()
{
    while(scanf("%d%d%d",&n,&m,&c)!=EOF)
    {
        init();
        tot=0;
        up(i,1,m)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w); addedge(v,u,w);
        }
        tot=0;
        up(i,0,c-1)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            addask(u,v); addask(v,u);
            _lca[i]=-1;
        }
        tot=0;
        up(i,1,n)
            if (!visit[i])
            {
                dist[i]=0;
                tarjan(i,++tot);
            }
        up(i,0,c-1)
            if (~_lca[i]) printf("%d\n",dist[_src[i*2]]+dist[_aim[i*2]]-2*dist[_lca[i]]);
            else printf("Not connected\n");
    }
}
rmq:
#define up(i, j, k) for(int i = j; i <= k; ++i)
#define down(i, j, k) for(int i = j; i >= k; --i)
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <map>

using namespace std;

int tot;
int aim[80010],len[80010],nxt[80010],first[40010];
int visit[40010],seq[80010],deep[80010],seqfirst[40010],dist[40010];
int dp[80010][18];

void addedge(int u,int v,int w)
{
    aim[tot]=v; len[tot]=w; nxt[tot]=first[u]; first[u]=tot++;
}

void dfs(int u,int dep)
{
    visit[u]=1; seq[++tot]=u; deep[tot]=dep; seqfirst[u]=tot;
    for(int i=first[u];~i;i=nxt[i])
    {
        if (!visit[aim[i]])
        {
            dist[aim[i]]=dist[u]+len[i];
            dfs(aim[i],dep+1);
            seq[++tot]=u; deep[tot]=dep;
        }
    }
}

void st(int n)
{
    up(i,1,n) dp[i][0]=i;
    for(int j=1;(1<<j)<=n;++j)
    {
        for(int i=1;i+(1<<j)-1<=n;++i)
        {
            int a=dp[i][j-1], b=dp[i+(1<<(j-1))][j-1];
            dp[i][j]=deep[a]<deep[b]?a:b;
        }
    }
}

int rmq(int l,int r)
{
    int k=log2(r-l+1);
    int a=dp[l][k],b=dp[r-(1<<k)+1][k];
    return deep[a]<deep[b]?a:b;
}

int lca(int u,int v)
{
    int l=seqfirst[u], r=seqfirst[v];
    if (l>r) swap(l,r);
    return seq[rmq(l,r)];
}

void init()
{
    memset(first,-1,sizeof(first));
    memset(visit,0,sizeof(visit));
    memset(seqfirst,0,sizeof(seqfirst));
    dist[1]=0;
}

int main()
{
    int t;
    scanf("%d",&t);
    while (t--)
    {
        init();
        int n,m;
        scanf("%d%d",&n,&m);
        tot=0;
        up(i,1,n-1)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w); addedge(v,u,w);
        }
        tot=0;
        dfs(1,1);
        st(2*n-1);
        up(i,1,m)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            printf("%d\n",dist[u]+dist[v]-2*dist[lca(u,v)]);
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值