tarjian(求最短距离)

http://acm.hdu.edu.cn/showproblem.php?pid=2586

题意:给出一颗n个节点,n-1边且有距离(带权),m次询问,问两点间最短距离。

解法:记录每一个节点到根节点(默认为1)距离,u、v两点距离为dis[u]+dis[v]-2*dis[fa].

//#include<bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string.h>
#include <vector>
#define ME(x , y) memset(x , y , sizeof(x))
#define SC scanf
#define rep(i , j , n) for(int i = j ; i <= n ; i++)
#define red(i , n , j)  for(int i = n ; i >= j ; i--)
#define INF  0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
typedef long long ll ;
const int maxn = 4e4+9;
int head[maxn] , qhead[maxn] , tol , qtol , vis[maxn] , f[maxn] , ans[maxn] , dis[maxn];
int n , m ;
struct node{
    int to , next , w;
}g[maxn<<1];

struct query{
    int to , next , id;
}q[maxn];

void init(){//初始化
    ME(head , 0);
    ME(qhead , 0);
    ME(vis , 0);
    ME(dis , 0);
    tol = 0 , qtol = 0;
    rep(i , 1 , n){
        f[i] = i ;
    }
 }

void add(int u , int v , int w){//建边
    g[++tol] = {v , head[u] , w};
    head[u] = tol ;
}

void qadd(int u , int v , int id){//需查询的两点
    q[++qtol] = {v , qhead[u] , id};
    qhead[u] = qtol;
}

int find(int x){
    return x == f[x] ? x :find(f[x]);
}
void unite(int u , int v){
    f[v] = u ;
}

void dfs(int u , int d){
    vis[u] = 1 ;
    for(int i = head[u] ; i ; i = g[i].next){
        int v = g[i].to;
        dis[u] = d ;
        if(vis[v]) continue;
        dfs(v , d+g[i].w);
        unite(u , v);
    }
    for(int i = qhead[u] ; i ; i = q[i].next){
        int v = q[i].to;
        if(vis[v]){
            int fa = find(v);
            ans[q[i].id] = dis[u] + dis[v] - 2*dis[fa];
        }
    }
}

void solve(){
    cin >> n >> m ;
    init();
    rep(i , 1 , n-1){
        int u , v , w ;
        scanf("%d%d%d" , &u , &v , &w);
        add(u , v , w);
        add(v , u , w);
    }
    rep(i , 1 , m){
        int u , v ;
        scanf("%d%d" , &u , &v);
        qadd(u , v , i);
        qadd(v , u , i);
    }
    dfs(1 , 0);
    rep(i , 1 , m){
        cout << ans[i] << endl;
    }
}

int main()
{
    int t;cin >> t ;
    while(t--){
        solve();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/nonames/p/12323881.html