HDU 2586 - How far away ? (LCA)

How far away ?

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


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
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   3486  2874  2888  3234  2818


题意:

给一棵n<=4000个点的树,树上的边有权值,然后给m<=200个询问,询问u到v的距离。


LCA


一:离线LCA,先把询问保存下来,然后求出询问的两点的LCA,然后输出答案


C++会爆栈,要手动开栈

#pragma comment(linker, "/STACK:102400000")

G++不会


这题数据太太太水了  我之前的程序连LCA都找错了



#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 40000 + 20;

struct Edge {
    int v, w;
    Edge(int v, int w) : v(v), w(w) {}
};

int n, m;
vector<Edge> G[maxn];
int dis[maxn];
int fa[maxn];
int ques[210][3];

int find(int x) {
    if(fa[x] == -1 || fa[x] == x) return x;
    return fa[x] = find(fa[x]);
}

void Union(int x, int y) {
    int fx = find(x);
    int fy = find(y);
    fa[fy] = fx;
}

void dfs(int u) {
    fa[u] = u;
    for(int i=0; i<G[u].size(); i++) {
        int v = G[u][i].v;
        int w = G[u][i].w;
        if(fa[v] == -1) {
            dis[v] = dis[u] + w;
            dfs(v);
            Union(u, v);
        }
    }
    for(int i=0; i<m; i++) if(ques[i][0] == u || ques[i][1] == u) {
        int v = ques[i][0] ^ ques[i][1] ^ u;
        ques[i][2] = find(v);
    }
}

int main() {
    int T;

    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        for(int i=1; i<=n; i++) G[i].clear();
        for(int i=1; i<n; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            G[u].push_back(Edge(v, w));
            G[v].push_back(Edge(u, w));
        }
        memset(fa, -1, sizeof(fa));
        for(int i=0; i<m; i++) {
            scanf("%d%d", &ques[i][0], &ques[i][1]);
        }
        dis[1] = 0;
        dfs(1);
        for(int i=0; i<m; i++) {
            int u = ques[i][0];
            int v = ques[i][1];
            int lca = ques[i][2];
            int ans = dis[u] + dis[v] - 2 * dis[lca];
            printf("%d\n", ans);
        }
    }

    return 0;
}




二:在线LCA



#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#pragma comment(linker, "/STACK:102400000")

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));

const int POW_M = 18;
const int maxn = 40000 + 20;

struct Edge {
    int v, w;
    Edge(int v=0, int w=0) : v(v), w(w) {}
};

vector<Edge> G[maxn];
int fa[maxn][POW_M];
int deep[maxn];
int dis[maxn];

void dfs(int u, int p) {
    fa[u][0] = p;
    for(int i=1; i<POW_M; i++) fa[u][i] = fa[fa[u][i-1]][i-1];
    int sz = G[u].size();
    for(int i=0; i<sz; i++) {
        int v = G[u][i].v;
        int w = G[u][i].w;
        if(v == p) continue;
        dis[v] = dis[u] + w;
        deep[v] = deep[u] + 1;
        dfs(v, u);
    }
}

int LCA(int u, int v) {
    if(deep[u] < deep[v]) swap(u, v);
    int d = deep[u] - deep[v];
    for(int i=0; i<POW_M; i++) if((1<<i) & d) {
        u = fa[u][i];
    }
    int i = POW_M - 1;
    while(u^v) {
        while(i && fa[u][i] == fa[v][i]) i--;
        u = fa[u][i];
        v = fa[v][i];
    }
    return u;
}

int main() {
    int T;

    scanf("%d", &T);
    while(T--) {
        int n, m;
        scanf("%d%d", &n, &m);
        for(int i=1; i<=n; i++) G[i].clear();
        for(int i=1; i<n; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            G[u].push_back(Edge(v, w));
            G[v].push_back(Edge(u, w));
        }
        fa[0][0] = 0;
        dis[1] = 0;
        deep[1] = 1;
        dfs(1, 0);
        for(int i=0; i<m; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            int fa = LCA(u, v);
            int ans = dis[u] + dis[v] - 2 * dis[fa];
            printf("%d\n", ans);
        }
    }

    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值