[UESTC 1437]谭松松的旅游计划

来源:互联网 发布:猿课软件 编辑:程序博客网 时间:2024/04/30 23:04

谭松松是一个爱旅游的人,他非常的热爱旅游,即便身体被掏空也要坚持旅游。喵蛤王国由N个城市组成,由N-1条道路连通,每条道路长度为ci,使得任意两座城市都能相互到达。谭松松有M个旅游计划,每个旅游计划有一个起点ai,一个终点bi,所以谭松松想知道,对于每个旅游计划,从起点到终点的最短路长度为多少?

输入:
第一行两个整数N(2≤N≤100000),M(1≤M≤100000),表示城市个数,谭松松的旅游计划个数。

接下来N-1行,每行三个整数li,ri,ci(1≤ci≤10000),表示li号城市和ri号城市之间有一条长度为ci的道路。

接下来M行,每行两个整数ai,bi表示旅游计划的起点和终点。

输出
输出M行,表示每个旅游计划的最短距离。

样例输入
7 6
1 2 5
1 3 4
3 7 7
2 4 4
2 5 3
5 6 2
1 2
4 7
6 3
3 2
5 4
7 6

样例输出
5
20
14
9
7
21

题解:由题意可知,所有的点在一颗树上,那么我们只需要找到a,b的最近公共祖先LCA(a,b),a,b之间的距离就是dis[a]+dis[b]-dis[LCA(a,b)]*2 (dis[i]表示从树的根节点到i点的距离),在线求LCA我们一般使用倍增算法,单次询问复杂度为O(logn)

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<vector>#define LiangJiaJun mainusing namespace std;int n,m,ne=1,h[100004],deep[100004],dis[100004];bool vis[100004];int fa[100004][24];queue<int>q;struct edge{    int to,next,w;}e[900004];void insert(int u,int v,int w){    e[++ne].to=v;e[ne].next=h[u];e[ne].w=w;h[u]=ne;}void RESET(){     memset(fa,0,sizeof(fa));     ne=1;memset(h,0,sizeof(h));     memset(vis,0,sizeof(vis));     memset(dis,127/3,sizeof(dis));     memset(deep,0,sizeof(deep));}void BFS(int st){     q.push(st);     dis[st]=0;     deep[st]=1;     while(!q.empty()){        int x=q.front();q.pop();        for(int i=h[x];i;i=e[i].next){            if(dis[e[i].to] > dis[x] + e[i].w){               dis[e[i].to] = dis[x] + e[i].w;               q.push(e[i].to);            }        }     }}void DFS(int x){     vis[x] = 1;     for(int i=1;i<=20;i++)fa[x][i] = fa[fa[x][i-1]][i-1];     for(int i=h[x];i;i=e[i].next){         if(vis[e[i].to])continue;         fa[e[i].to][0]=x;         deep[e[i].to]=deep[x]+1;         DFS(e[i].to);     }}int LCA(int u,int v){    if(deep[u]<deep[v])swap(u,v);    int dva=deep[u]-deep[v];    for(int i=0;i<=20;i++)        if(dva&(1<<i))u=fa[u][i];    for(int i=20;i>=0;i--){        if(fa[u][i]!=fa[v][i]){           u=fa[u][i];           v=fa[v][i];        }    }    if(u==v)return u;    return fa[u][0];}void work(){     RESET();     for(int i=1;i<n;i++){         int u,v,w;         scanf("%d%d%d",&u,&v,&w);         insert(u,v,w);insert(v,u,w);     }     BFS(1);     DFS(1);     while(m--){        int a,b,t;        scanf("%d%d",&a,&b);        t=LCA(a,b);        printf("%d\n",dis[a]+dis[b]-dis[t]*2);     }}int LiangJiaJun(){    while(scanf("%d%d",&n,&m)!=EOF)work();    return 0;}
0 0