LCA模板在线 POJ 1986 Distance Queries

传送门


题目大意:
给出n个点m条边,输入m行每行3个数字,1个字母,分别是边的端点和权值,字母么??打酱油的…然后k个询问,询问树上x~y的路径长度


Attention!!please!!
n<=10W不是4W,WA了好多遍O(≧口≦)O


分析:
这妥妥のLCA…
在线算法……
倍增法求LCA…..
很好理解,不再解释,直接上代码….


代码如下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=100000+5;
int n,m,k,cnt,hd[maxn],to[maxn*2],nxt[maxn*2],w[maxn],fa[maxn][35],dep[maxn],dis[maxn];
char djyd[10];
inline void add(int x,int y,int s){
    w[cnt]=s;
    to[cnt]=y;
    nxt[cnt]=hd[x];
    hd[x]=cnt++;
}
inline void init(){
    for(int j=1;j<=30;j++)
        for(int i=1;i<=n;i++)
            fa[i][j]=fa[fa[i][j-1]][j-1];
}
inline void dfs(int root,int f){
    for(int i=hd[root];i!=-1;i=nxt[i])
        if(to[i]!=f)
            fa[to[i]][0]=root,dis[to[i]]=dis[root]+w[i],dep[to[i]]=dep[root]+1,dfs(to[i],root);
}
inline int LCA(int a,int b){
    if(dep[a]<dep[b])
        swap(a,b);
    int d=dep[a]-dep[b];
    for(int i=0;i<=30;i++)
        if((1<<i)&d)
            a=fa[a][i];
    if(a==b)
        return b;
    for(int i=30;i>=0;i--)
        if(fa[a][i]!=fa[b][i])
            a=fa[a][i],b=fa[b][i];
    return fa[a][0];
}
signed main(void){
    while(scanf("%d%d",&n,&m)!=EOF){
        cnt=0,memset(hd,-1,sizeof(hd));
        for(int i=1,x,y,z;i<=m;i++)
            scanf("%d%d%d%s",&x,&y,&z,djyd),add(x,y,z),add(y,x,z);
        fa[1][0]=1,dep[1]=dis[1]=0,dfs(1,-1),init(),scanf("%d",&k);
        for(int i=1,x,y;i<=k;i++)
            scanf("%d%d",&x,&y),cout<<dis[x]+dis[y]-2*dis[LCA(x,y)]<<endl;
    }
    return 0;
}

by >_< neighthorn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值