HDU2586 How far away ?

来源:互联网 发布:知乎 酒吧假酒 编辑:程序博客网 时间:2024/05/01 18:16

LCA-ST算法

题目传送门

刚学LCA的蒟蒻的我,只能找找模板题练练手喽o(╯□╰)o

给你一棵树及各个边的权值,Q个询问求x到y的最小代价。
直接ST上去就把它干翻#手动滑稽(Tarjan仍然在学,原谅蒟蒻的我)(已经填坑2017.10.6)
求x到y的最小代价,可以转化为从根节点到x的距离加上到y的距离减去两倍到LCA的距离。然后只要求出LCA就可以啦!
LCA不会?来自本蒟蒻的Blog

蒟蒻代码:

#include<cstdio>#include<cstring>#include<algorithm>#define MAXN 40000using namespace std;struct edge{    int next;    int to;    int dis;};int fa[MAXN+5][20],h[MAXN+5],dis[MAXN+5],depth[MAXN+5];int n,m,k,u,v,d,t;edge ed[MAXN*2+5];void read(int x,int y,int z){    k++;    ed[k].next=h[x];    ed[k].to=y;    ed[k].dis=z;    h[x]=k;}void dfs(int x){    for (int i=h[x];i;i=ed[i].next)        if (ed[i].to!=fa[x][0]){            int now=ed[i].to;            fa[now][0]=x;            depth[now]=depth[x]+1;            dis[now]=dis[x]+ed[i].dis;            dfs(now);        }}void findfather(){    for (int j=1;j<=15;j++)        for (int i=1;i<=n;i++)            fa[i][j]=fa[fa[i][j-1]][j-1];}int LCA(int x,int y){    if (depth[x]<depth[y]) swap(x,y);    for (int i=15;i>=0;i--)        if (depth[fa[x][i]]>=depth[y]) x=fa[x][i];    if (x==y) return x;    for (int i=15;i>=0;i--)        if (fa[x][i]!=fa[y][i]){            x=fa[x][i]; y=fa[y][i];        }    return fa[x][0];}int main(){    scanf("%d",&t);    while (t--){        scanf("%d%d",&n,&m);        memset(h,0,sizeof(h));        k=0;        for (int i=1;i<n;i++){            scanf("%d%d%d",&u,&v,&d);            read(u,v,d);            read(v,u,d);        }        fa[1][0]=1; depth[1]=0; dis[1]=0;        dfs(1);         findfather();        for (int i=1;i<=m;i++){            int x,y;            scanf("%d%d",&x,&y);            int lca=LCA(x,y);            printf("%d\n",dis[x]+dis[y]-dis[lca]-dis[lca]);        }    }    return 0;}
原创粉丝点击