题干:
You are given a tree (an undirected acyclic connected graph) withNnodes, 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 integert, the number of test cases (t<= 25).ttest 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
解题报告:
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 20000 + 5;
int dep[MAX],fa[MAX][33],cost[MAX][33];
int n,m;
vector<int> vv[MAX];
vector<int> ww[MAX];
void dfs(int cur, int rt) {
fa[cur][0] = rt;
dep[cur] = dep[rt] + 1;
for(int i = 1; i < 31; ++i) {
fa[cur][i] = fa[fa[cur][i - 1]][i - 1];
cost[cur][i] = cost[fa[cur][i - 1]][i - 1] + cost[cur][i - 1];
}
int sz = vv[cur].size();
for (int i = 0; i < sz; ++i) {
if (vv[cur][i] == rt) continue;
cost[vv[cur][i]][0] = ww[cur][i];
dfs(vv[cur][i], cur);
}
}
int lca(int u,int v) {
if(dep[u] < dep[v]) swap(u,v);
int res = 0;
int dc = dep[u]-dep[v];
for(int i = 0; i<=30; i++) {
if((1<<i) & dc) res += cost[u][i],u=fa[u][i];
}
if(u == v) return res;
for(int i = 30; i>=0 && u!=v; i--) {
if(fa[u][i] != fa[v][i]) {
res += cost[v][i] + cost[u][i];
u=fa[u][i];
v=fa[v][i];
}
}
res += cost[u][0] + cost[v][0];
u=fa[u][0];
return res;
}
int fk(int a,int b,int k) {
int u=a,v=b;
if(dep[u] < dep[v]) swap(u,v);
int dc = dep[u]-dep[v];
for(int i = 0; i<=30; i++) {
if((1<<i) & dc) u=fa[u][i];
}
if(u!=v) {
for(int i = 30; i>=0 && u!=v; i--) {
if(fa[u][i] != fa[v][i]) {
u=fa[u][i];
v=fa[v][i];
}
}
u=fa[u][0];//得到公共祖先
}
int cur = 0;
int ans = 0;
if(dep[a] - dep[u] >= k) {
int RES = k-1;
if(RES!=0) {
for(int i = 30; i>=0; i--) {
int now = fa[a][i];
if(dep[a] - dep[now] < RES) {
int tmp = dep[a] - dep[now];
a = fa[a][i];
RES -= tmp;
}
}
ans = fa[a][0];
} else ans = a;
} else if(dep[a] - dep[u] == k-1) {
ans = u;
} else {
int RES = k - (dep[a] - dep[u])-1;
RES = (dep[b]-dep[u]-RES);
if(RES != 0) {
for(int i = 30; i>=0; i--) {
int now = fa[b][i];
if(dep[b] - dep[now] < RES) {
int tmp = dep[b] - dep[now];
b = fa[b][i];
RES -= tmp;
}
}
ans = fa[b][0];
}
else ans = b;
}
return ans;
}
int main() {
int t;
cin>>t;
while(t--) {
scanf("%d",&n);
memset(dep,0,sizeof dep);
memset(fa,0,sizeof fa);
memset(cost,0,sizeof cost);
for(int i = 1; i<=n; i++) vv[i].clear(),ww[i].clear();
for(int a,b,c,i = 1; i<=n-1; i++) {
scanf("%d%d%d",&a,&b,&c);
vv[a].pb(b);
vv[b].pb(a);
ww[a].pb(c);
ww[b].pb(c);
}
dfs(1,-1);
char op[22];
while(scanf("%s",op)) {
int a,b,k;
if(!strcmp(op,"DIST")) {
scanf("%d%d",&a,&b);
printf("%d\n",lca(a,b));
} else if(!strcmp(op,"KTH")) {
scanf("%d%d%d",&a,&b,&k);
printf("%d\n",fk(a,b,k));
} else break;
}
if(t) puts("");
}
return 0 ;
}