A - How far away ?

来源:互联网 发布:淘宝男装首页文案范文 编辑:程序博客网 时间:2024/04/18 11:56

A - How far away ?
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
 

Input

First line is a single integer T(T<=10), indicating the number of test cases. 
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n. 
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
 

Output

For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
 

Sample Input

23 21 2 103 1 151 22 32 21 2 1001 22 1
 

Sample Output

1025100100

这道题的意思是有n个房子和n-1条边,每两个房子之间只有一条路径,询问从u到v之间的最短路径,既需要寻找到这两个点的最近的祖先,然后通过最近的祖先到达,这条路即为最短路。LCA&RMQ,LCA是在一棵树中寻找两点的最近祖先,RMQ是在一段数列中寻找最小或最大的值,这里用RMQ来寻找深度序列中的最小值。先用dfs深度遍历跑一遍,把深度序列及每个元素第一次出现的位置pos还有依次跑过的点seq记录下来,再用RMQ计算出任意一点开始长度为2的i次幂的区间中最小的深度所对应的真正元素序列的下标,然后每一个询问就直接求出两个点之间的dp最小值,对应的seq即为最近祖先,两点之间的最短距离是dis[u]+dis[v]-2*dis[lca].有一个不需要考虑的地方就是,每一组测试后输出一行空格,我另外输出了一空行,结果错的

#include <iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>#define maxn 80100using namespace std;struct node{    int en,next,len;}e[maxn];int n,num,cnt;int head[maxn],seq[maxn],mark[maxn],deep[maxn],dis[maxn],pos[maxn];int dp[maxn][30];void add(int a,int b,int c){    e[num].en=b;    e[num].next=head[a];    e[num].len=c;    head[a]=num++;}void dfs(int u,int d){    mark[u]=1;    seq[++cnt]=u;    pos[u]=cnt;    deep[cnt]=d;    for(int i=head[u];i!=-1;i=e[i].next)    {        int en=e[i].en;        if(!mark[en])        {            int len=e[i].len;            dis[en]=len+dis[u];            dfs(en,d+1);            seq[++cnt]=u;            deep[cnt]=d;        }    }}void rmq(){    int i,j;    for(i=0;i<cnt;i++)        dp[i][0]=i;    for(i=1;(1<<i)<=cnt;i++)        for(j=1;j+(1<<i)<=cnt;j++)    {        int a=dp[j][i-1],b=dp[j+(1<<(i-1))][i- 1];        dp[j][i]=deep[a]<deep[b]?a:b;    }}int lca(int a,int b){    int x=pos[a],y=pos[b];    if(x>y) swap(x,y);    int k=(int)(log(double(y-x+1))/log(2.0));    int xx=dp[x][k],yy=dp[y-(1<<k)+1][k];    int t=deep[xx]<deep[yy]?xx:yy;    return seq[t];}int main(){    ios_base::sync_with_stdio(0);    cin.tie(0);    cout.tie(0);    int t,m;    cin>>t;    while(t--)    {        memset(mark,0,sizeof(mark));        memset(head,-1,sizeof(head));        num=0;        cin>>n>>m;        int a,b,c;        for(int i=0;i<n-1;i++)        {            cin>>a>>b>>c;            add(a,b,c);            add(b,a,c);        }        cnt=0;        dfs(1,1);        rmq();        while(m--)        {            cin>>a>>b;            int lcan=lca(a,b);            cout<<dis[a]+dis[b]-2*dis[lcan]<<endl;        }    }    return 0;}

0 0
原创粉丝点击