LCA转RMQ 在线算法模板

来源:互联网 发布:fifaol3数据库 编辑:程序博客网 时间:2024/06/06 01:06

hdu 2586

#include<iostream>

#include<fstream>
#include<set>
#include<stack>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;


typedef long long LL;
const int MAX=0xfffffff;
const int mn=44000;
int e;
struct node{
    int to,next;
    int w;
}edge[mn*2];
int head[mn];
bool visit[mn];
int n,q;
int tot;
void init()
{
    e=0;
    memset(head,-1,sizeof(head));
    memset(visit,0,sizeof(visit));
}
void add(int u,int v,int w)
{
    edge[e].to=v,edge[e].w=w;
    edge[e].next=head[u],head[u]=e++;
}
int ver[mn*2];//遍历过程中的某次访问的点
int R[mn*2];// 某个编码次序的深度
int first[mn];//第一次出现某点的次序
int dir[mn];
void dfs(int u,int dep)
{
    visit[u]=1;ver[++tot]=u;first[u]=tot;R[tot]=dep;
    for(int k=head[u];k!=-1;k=edge[k].next)
        if(!visit[edge[k].to])
        {
            dir[edge[k].to]=dir[u]+edge[k].w;
            dfs(edge[k].to,dep+1);
            ver[++tot]=u,R[tot]=dep;
        }
}
int dp[mn*2][25];
void ST(int n)
{
    for(int i=1;i<=n;i++)  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]=R[a]<R[b]?a:b;
        }
}
int RMQ(int l,int r)
{
    int k=0;
    while(1<<(k+1)<=r-l+1)
        k++;
    int a=dp[l][k],b=dp[r-(1<<k)+1][k];
    return R[a]<R[b]?a:b;
}
int LCA(int u,int v)
{
    int x=first[u],y=first[v];
    if(x>y)  swap(x,y);
    int res=RMQ(x,y);
    return ver[res];
}
int main( )
{
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d %d",&n,&q);
        for(int i=1;i<n;i++)
        {
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        tot=0,dir[1]=0;
        dfs(1,1);
        ST(2*n-1);
        while(q--)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            int lca=LCA(u,v);
            printf("%d\n",dir[u]+dir[v]-2*dir[lca]);
        }
    }
    return 0;
}
0 0
原创粉丝点击