`
Simone_chou
  • 浏览: 183855 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

How far away ?(LCA 在线算法RMQ)

    博客分类:
  • HDOJ
 
阅读更多

How far away ?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5810    Accepted Submission(s): 2182


Problem 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
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

     

      题意:

      给出 T(0 ~ 10) 组 case,每个 case 给出 N(2 ~ 40000) 个节点和 M (1 ~ 200)个询问,后给出 N - 1 条边的两节点和权值。每次询问输出一个答案,输出 a 到 b 的距离。

 

      思路:

      LCA。RMQ 的在线算法,任何一个根为起点都可以,dfs 的时候顺便用 dis 记录到根的距离,求出 a 和 b 的 LCA c,则距离等于 dis [ a ] + dis [ b ] - 2 X dis [ c ]。因为 RMQ 数组的长度开小了,所以 WA 了很多遍。

 

       AC:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int VMAX = 40010;
const int EMAX = VMAX * 10;

int n, ind;
int next[EMAX], fir[VMAX], w[EMAX], v[EMAX];

int k;
int dis[VMAX], vs[VMAX * 5], dep[VMAX * 5], id[VMAX];
bool vis[VMAX];

int dp[VMAX * 5][25];

void init () {
    ind = k = 0;
    memset(fir, -1, sizeof(fir));
    memset(vis, 0, sizeof(vis));
}

void add_edge (int f, int t, int val) {
    v[ind] = t;
    w[ind] = val;
    next[ind] = fir[f];
    fir[f] = ind;
    ++ind;
}

void dfs (int x, int d) {
    id[x] = k;
    vs[k] = x;
    dep[k++] = d;
    vis[x] = 1;

    for (int e = fir[x]; e != -1; e = next[e]) {
        int V = v[e];
        if (!vis[V]) {
            dis[V] = dis[x] + w[e];
            dfs(V, d + 1);
            vs[k] = x;
            dep[k++] = d;
        }
    }
}

void RMQ_init () {
    for (int i = 0; i < k; ++i) dp[i][0] = i;

    for (int j = 1; (1 << j) <= k; ++j) {
        for (int i = 0; i + (1 << j) - 1 < k; ++i) {
            int a = dp[i][j - 1];
            int b = dp[i + (1 << (j - 1))][j - 1];
            if (dep[a] > dep[b]) dp[i][j] = b;
            else dp[i][j] = a;
        }
    }
}

int RMQ (int L, int R) {
    int len = 0;
    while ((1 << (len + 1)) <= (R - L + 1)) ++len;

    int a = dp[L][len];
    int b = dp[R - (1 << len) + 1][len];

    if (dep[a] > dep[b]) return b;
    return a;
}

int LCA (int a, int b) {
    int L = min(id[a], id[b]);
    int R = max(id[a], id[b]);
    int Min = RMQ(L, R);
    return vs[Min];
}

int main () {

    int T;
    scanf("%d", &T);

    while (T--) {
        init();

        int m;
        scanf("%d%d", &n, &m);

        for (int i = 1; i <= n - 1; ++i) {
            int a, b, val;
            scanf("%d%d%d", &a, &b, &val);
            add_edge(a, b, val);
            add_edge(b, a, val);
        }

        dfs (1, 1);

        RMQ_init();

        while (m--) {
            int a, b;
            scanf("%d%d", &a, &b);

            int node = LCA(a, b);
            printf("%d\n", dis[a] + dis[b] - 2 * dis[node]);
        }

    }

    return 0;
}

 

  

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics