HDU 2586 - How far away ? (LCA)

来源:互联网 发布:中教数据库怎么样 编辑:程序博客网 时间:2024/05/22 06:42

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
23 21 2 103 1 151 22 32 21 2 1001 22 1
 

Sample Output
1025100100
 

Source
ECJTU 2009 Spring Contest
 

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 WINtypedef __int64 LL;#define iform "%I64d"#define oform "%I64d\n"#define oform1 "%I64d"#elsetypedef 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 WINtypedef __int64 LL;#define iform "%I64d"#define oform "%I64d\n"#define oform1 "%I64d"#elsetypedef 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;}





0 0
原创粉丝点击