You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, representing its length.
We will ask you to perfrom some instructions of the following form:
Example:
N = 6
1 2 1 // edge connects node 1 and node 2 has cost 1
2 4 1
2 5 2
1 3 1
3 6 2
Path from node 4 to node 6 is 4 -> 2 -> 1 -> 3 -> 6
DIST 4 6 : answer is 5 (1 + 1 + 1 + 2 = 5)
KTH 4 6 4 : answer is 3 (the 4-th node on the path from node 4 to node 6 is 3)
The first line of input contains an integer t, the number of test cases (t <= 25). t test cases follow.
For each test case:
There is one blank line between successive tests.
For each "DIST" or "KTH" operation, write one integer representing its result.
Print one blank line after each test.
Input: 1 6 1 2 1 2 4 1 2 5 2 1 3 1 3 6 2 DIST 4 6 KTH 4 6 4 DONE Output: 5 3
LCA, 开disRt[u]数组表示节点u到根的距离,用倍增法求节点u与v的LCA(w), 则dis(u, v) = (disRt[u] - disRt[w]) + (disRt[v] - disRt[w]). u至v路径上第k个节点则讨论其实u的祖先还是v的祖先, 再二分查找即可.
#include <cstdio> #include <iostream> #include <cstdlib> #include <memory.h> #include <ctime> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <utility> #include <stack> #include <set> #include <map> #include <queue> #include <vector> #include <climits> using namespace std; #define clr(_arr) (memset(_arr, 0, sizeof(_arr))) typedef long long ll; const int INF = INT_MAX, N_MAX = 10010, LG_N_MAX = 20; int N, LG_N, a, b, c, root = 1, par[LG_N_MAX][N_MAX],//par[m][u] indicates the (2 ^ m)th ancestor of u dep[N_MAX], disRt[N_MAX]; char instr[8]; vector<int> G[N_MAX]; typedef pair<int, int> pii; map<pii, int> len; void init() { clr(par); clr(dep); clr(disRt); for (int i = 1; i <= N; ++i) G[i].clear(); len.clear(); LG_N = 0; int _N = 1; while (_N <= N) { _N <<= 1; ++LG_N; } ++LG_N; } void addEdge(int a, int b, int c) { G[a].push_back(b); G[b].push_back(a); len[make_pair(a, b)] = c; len[make_pair(b, a)] = c; } void dfs(int u, int p, int d, int dR) { par[0][u] = p; dep[u] = d; disRt[u] = dR; int out = G[u].size(); for (int i = 0; i < out; ++i) { int s = G[u][i]; if (s != p) dfs(s, u, d + 1, dR + len[pii(u, s)]); } } void pre() { dfs(root, -1, 0, 0); //par[m + 1][u] can be obtained only after all par[m][v](v = 1..N) is obtained, and thus the outer loop should be of u for (int u = 1; u <= N; ++u) for (int m = 0; m + 1 <= LG_N; ++m) { if (par[m][u] < 0) par[m + 1][u] = -1; else par[m + 1][u] = par[m][par[m][u]]; } } int kthAnt(int u, int k) { for (int m = 0; k; ++m, k >>= 1) { if (k & 1) u = par[m][u]; } return u; } int LCA(int u, int v) { if (dep[u] < dep[v]) swap(u, v); u = kthAnt(u, dep[u] - dep[v]); if (u == v) return u; //binary search, search all ancestors of u and v for the last different node index pair, whose parent is LCA(u, v) for (int m = LG_N; m >= 0; --m) if (par[m][u] != par[m][v]) { u = par[m][u]; v = par[m][v]; } return par[0][u]; } int Kth(int u, int v, int k) { int w = LCA(u, v); int uw = dep[u] - dep[w] + 1, wv = dep[v] - dep[w] + 1, _k = k; k = (_k <= uw) ? k : (wv - (k - uw)); u = (_k <= uw) ? u : v; return kthAnt(u, k - 1); } int main() { int t; scanf("%d", &t); while(t--) { bool done = false; scanf("%d", &N); init(); for (int i = 1; i < N; ++i) { scanf("%d %d %d", &a, &b, &c); addEdge(a, b, c); } pre(); getchar(); while(!done) { scanf("%s", instr); switch (instr[1]) { case ‘I‘: { scanf("%d %d\n", &a, &b); int w = LCA(a, b); int dis = disRt[a] + disRt[b] - 2 * disRt[w]; printf("%d\n", dis); break; } case ‘T‘: { int k; scanf("%d %d %d\n", &a, &b, &k); printf("%d\n", Kth(a, b, k)); break; } case ‘O‘: { done = true; break; } } } printf("\n"); } return 0; }
原文:http://www.cnblogs.com/YangXuanyue/p/4700200.html