2015-02-09 11:20:50
思路:比较裸的树上倍增,用的二分倍增。
至于距离的计算,只要用dis数组记录下每个节点到根的距离,然后u点和v点之间的距离就是:dis[u] + dis[v] - 2 * dis[lca]
嘛... 要敲扩栈命令喔~
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <stack> 10 #include <queue> 11 #include <string> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 #define MEM(a,b) memset(a,b,sizeof(a)) 17 #define REP(i,n) for(int i=1;i<=(n);++i) 18 #define REV(i,n) for(int i=(n);i>=1;--i) 19 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 20 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 21 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 22 #define MP(a,b) make_pair(a,b) 23 24 typedef long long ll; 25 typedef pair<int,int> pii; 26 const int INF = (1 << 30) - 1; 27 const int MAXN = 40010; 28 const int MAX_LOG = 16; 29 30 int T,n,m; 31 int first[MAXN],ecnt; 32 int fa[MAX_LOG][MAXN],dep[MAXN]; 33 ll dis[MAXN]; 34 35 struct edge{ 36 int v,next,w; 37 }e[MAXN << 1]; 38 39 void Add_edge(int u,int v,int c){ 40 e[++ecnt].next = first[u]; 41 e[ecnt].v = v; 42 e[ecnt].w = c; 43 first[u] = ecnt; 44 } 45 46 void Dfs(int p,int pre,int d){ 47 fa[0][p] = pre; 48 dep[p] = d; 49 for(int i = first[p]; ~i; i = e[i].next){ 50 int v = e[i].v; 51 if(v == pre) continue; 52 dis[v] = dis[p] + e[i].w; 53 Dfs(v,p,d + 1); 54 } 55 } 56 57 void Pre(){ 58 dis[1] = 0; 59 Dfs(1,-1,0); 60 for(int k = 0; k + 1 < MAX_LOG; ++k){ 61 for(int v = 1; v <= n; ++v){ 62 if(fa[k][v] < 0) fa[k + 1][v] = -1; 63 else fa[k + 1][v] = fa[k][fa[k][v]]; 64 } 65 } 66 } 67 68 int Lca(int u,int v){ 69 if(dep[u] > dep[v]) swap(u,v); 70 for(int k = MAX_LOG - 1; k >= 0; --k){ 71 if((dep[v] - dep[u]) & (1 << k)) 72 v = fa[k][v]; 73 } 74 if(u == v) return u; //u为v的根 75 for(int k = MAX_LOG - 1; k >= 0; --k){ 76 if(fa[k][u] != fa[k][v]){ 77 u = fa[k][u]; 78 v = fa[k][v]; 79 } 80 } 81 return fa[0][u]; //u离lca只差一步 82 } 83 84 int main(){ 85 int a,b,c; 86 scanf("%d",&T); 87 REP(tt,T){ 88 MEM(first,-1); 89 ecnt = 0; 90 scanf("%d%d",&n,&m); 91 REP(i,n - 1){ 92 scanf("%d%d%d",&a,&b,&c); 93 Add_edge(a,b,c); 94 Add_edge(b,a,c); 95 } 96 Pre(); 97 REP(i,m){ 98 scanf("%d%d",&a,&b); 99 int lca = Lca(a,b); 100 printf("%I64d\n",dis[a] + dis[b] - (dis[lca] << 1)); 101 } 102 } 103 return 0; 104 }