HDU - 2586 How far away ?

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.

InputFirst 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.OutputFor each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.Sample Input

2
3 2
1 2 10
3 1 15
1 2
2 3

2 2
1 2 100
1 2
2 1

Sample Output

10
25
100
100
#include <bits/stdc++.h>
using namespace std;
#define ll long long
using namespace std;
const int mod = 1e9+7;/// 998244353;
const int mxn = 5e4 +7;
int _,m,n,t,k,ans,cnt,lg;
struct e{
    int to,x,nx;
}e[40000*2+7];
int dep[mxn] , f[mxn][30] , len[mxn] , head[mxn] ;
void add(int u,int v,int w)
{
    e[cnt].to = v;
    e[cnt].x = w ;
    e[cnt].nx = head[u];
    head[u] = cnt++;
}
void bfs()
{
    memset(f,0,sizeof(f));
    memset(dep,0.,sizeof(dep));
    queue<int>q;
    q.push(1);
    dep[1] = 1 ;
    while(!q.empty())
    {
        int u = q.front() ; q.pop() ;
        for(int i=head[u] ; ~i ;i = e[i].nx)
        {
            int v = e[i].to ;
            if(dep[v]) continue;
            len[v] = len[u] + e[i].x;
            dep[v] = dep[u] + 1 ;
            f[v][0] = u ; /// 存储父节点
            for(int j=1;j<=lg;j++)
                f[v][j] = f[ f[v][j-1] ][j-1] ;
            q.push(v);
        }
    }
}
int lca(int u,int v)
{
    if(dep[u]>dep[v] ) swap(u,v);
    for(int i=lg;i>=0;i--) /// 提升 V 和 U 至相同的高度
        if( dep[ f[v][i] ] >= dep[u] )
            v = f[v][i] ; 
    if(v==u) return u ;
    for(int i=lg;i>=0;i--) /// 找到最近的 LCA 
        if( f[u][i] != f[v][i] )
            u = f[u][i] , v = f[v][i] ;
    return f[u][0];
}
void solve()
{
    for(cin>>t;t;t--)
    {
        cin>>n>>m;
        cnt = 0 ; lg = int(log(n)/log(2))+1; 
        memset(head,-1,sizeof(head));
        for(int i=1,u,v,w;i<n;i++){
            cin>>u>>v>>w;
            add(u,v,w);
            add(v,u,w);
        }
        bfs();
        while(m--)
        {
            int u , v ;
            cin>>u>>v;
            cout<<len[u]+len[v] - 2*len[ lca(u,v) ]<<endl;
        }

    }
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    solve();
}
View Code

猜你喜欢

转载自www.cnblogs.com/Shallow-dream/p/13401951.html
今日推荐