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.
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
题意:
给一棵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;
}