HDU2586 离线tarjan LCA

来源:互联网 发布:listview滑动卡顿优化 编辑:程序博客网 时间:2024/05/05 07:12

离线LCA求一棵树上的两点间的最近距离

#include <iostream>#include <vector>#include <cstdio>#include <cstring>#define maxn 41111using namespace std;struct node{    int v,next,len;}edge[84444];struct que{    int u,v,next,id;}ask[422];int father[maxn],vis[maxn],ans[maxn],in[maxn],lca[222];int head[44444],h[44444],dis[44444];int n,m,c,e,q;void addedge(int u,int v,int w){    edge[e].v = v;    edge[e].len = w;    edge[e].next = head[u];    head[u] = e++;}void addquery(int u,int v,int w){    ask[q].v = v;    ask[q].u = u;    ask[q].id = w;    ask[q].next = h[u];    h[u] = q++;}void init(){    for(int i = 0 ; i <= n ; i ++){        father[i] = i;        vis[i] = 0;        dis[i] = 0;    }    memset(head,-1,sizeof(head));    memset(h,-1,sizeof(h));    e = 0;    q = 0;}int find(int x){    if(father[x] == x)        return x;    int t = find(father[x]);    father[x] = t;    return t;}void LCA(int u){    father[u] = u;    vis[u] = 1;    for(int i = h[u] ; i != -1 ; i = ask[i].next){        int v = ask[i].v;        if(vis[v] == 1){            int root = find(v);            lca[ask[i].id] = root;        }    }    for(int i = head[u] ; i != -1 ; i = edge[i].next){        int v = edge[i].v;        if(!vis[v]){            dis[v] = dis[u] + edge[i].len;            LCA(v);            father[v] = u;        }    }}int main(){    int T;    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&m);        init();        for(int i = 1 ; i < n ; i++){            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            addedge(u,v,w);            addedge(v,u,w);        }        for(int i = 0 ; i < m ; i ++){            int a,b;            scanf("%d%d",&a,&b);            addquery(a,b,i);            addquery(b,a,i);        }        LCA(1);        for(int i = 0 ; i < q ; i += 2){            printf("%d\n",dis[ask[i].u]+dis[ask[i].v]-2*dis[lca[ask[i].id]]);        }    }    return 0;}


原创粉丝点击