[bzoj] 1602 牧场行走
Posted Lev今天学习了吗
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj] 1602 牧场行走相关的知识,希望对你有一定的参考价值。
1602: [Usaco2008 Oct]牧场行走
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 2013 Solved: 1059
Description
N头牛(2<=n<=1000)别人被标记为1到n,在同样被标记1到n的n块土地上吃草,第i头牛在第i块牧场吃草。 这n块土地被n-1条边连接。 奶牛可以在边上行走,第i条边连接第Ai,Bi块牧场,第i条边的长度是Li(1<=Li<=10000)。 这些边被安排成任意两头奶牛都可以通过这些边到达的情况,所以说这是一棵树。 这些奶牛是非常喜欢交际的,经常会去互相访问,他们想让你去帮助他们计算Q(1<=q<=1000)对奶牛之间的距离。
Input
*第一行:两个被空格隔开的整数:N和Q
*第二行到第n行:第i+1行有两个被空格隔开的整数:AI,BI,LI
*第n+1行到n+Q行:每一行有两个空格隔开的整数:P1,P2,表示两头奶牛的编号。
Output
*第1行到第Q行:每行输出一个数,表示那两头奶牛之间的距离。
Sample Input
4 2
2 1 2
4 3 2
1 4 3
1 2
3 2
2 1 2
4 3 2
1 4 3
1 2
3 2
Sample Output
2
7
7
Source
Analysis
树上求两点间距离,倍增求LCA顺带维护倍增距离即可。
Code
1 #include<cstdio> 2 #include<iostream> 3 #define maxn 20005 4 using namespace std; 5 6 struct edge{ 7 int from,v,len; 8 }e[maxn]; 9 10 int tot,first[maxn],n,q,a,b,c; 11 void insert(int u,int v,int len){ 12 tot++; 13 e[tot].from = first[u]; 14 e[tot].v = v; 15 e[tot].len = len; 16 first[u] = tot; 17 } 18 19 bool book[maxn]; int depth[maxn],fa[maxn][20],cost[maxn][20]; 20 void dfs(int now){ 21 for(int i = first[now];i;i = e[i].from){ 22 int v = e[i].v; 23 if(!book[v]){ 24 book[v] = true; 25 depth[v] = depth[now]+1; 26 fa[v][0] = now; 27 cost[v][0] = e[i].len; 28 for(int i = 1;i <= 18;i++) 29 fa[v][i] = fa[fa[v][i-1]][i-1], 30 cost[v][i] = cost[fa[v][i-1]][i-1]+cost[v][i-1]; 31 dfs(v); 32 } 33 } 34 } 35 36 int LCA(int u,int v){ 37 int ans = 0; 38 if(depth[u] < depth[v]) swap(u,v); 39 for(int i = 18;i >= 0;i--) 40 if(depth[fa[u][i]] >= depth[v]) 41 ans += cost[u][i],u = fa[u][i]; 42 if(u == v) return ans; 43 for(int i = 18;i >= 0;i--) 44 if(fa[u][i] != fa[v][i]) 45 ans += cost[u][i]+cost[v][i], 46 u = fa[u][i],v = fa[v][i]; 47 return ans+cost[u][0]+cost[v][0]; 48 } 49 50 int main(){ 51 scanf("%d%d",&n,&q); 52 53 for(int i = 1;i < n;i++){ 54 scanf("%d%d%d",&a,&b,&c); 55 insert(a,b,c); 56 insert(b,a,c); 57 } 58 59 book[1] = true; 60 depth[1] = 1; 61 dfs(1); 62 63 // for(int i = 0;i <= n;i++){ 64 // for(int j = 0;j <= 18;j++){ 65 // printf("%d ",fa[i][j]); 66 // }cout << endl; 67 // } 68 69 for(int i = 0;i < q;i++){ 70 scanf("%d%d",&a,&b); 71 printf("%d\n",LCA(a,b)); 72 } 73 74 return 0; 75 }
以上是关于[bzoj] 1602 牧场行走的主要内容,如果未能解决你的问题,请参考以下文章