vijos p1460——拉力赛
描述
车展结束后,游乐园决定举办一次盛大的山道拉力赛,平平和韵韵自然也要来参加大赛。
赛场上共有n个连通的计时点,n-1条赛道(构成了一棵树)。每个计时点的高度都不相同(父结点的高度必然大于子结点),相邻计时点间由赛道相连。由于马力不够,所以韵韵的遥控车只能从高处驶向低处。而且韵韵的车跑完每条赛道都需花费一定的时间。
举办方共拟举办m个赛段的比赛,每次从第u个计时点到第v个计时点,当然其中有不少比赛韵韵的遥控车是不能参加的(因为要上坡)。平平想知道他能参加多少个赛段的比赛,并且想知道他完成这些赛段的总用时。
赛道皆为单向。
格式
输入格式
第一行两个整数n,m。
接下来n-1行每行3个整数a、b、t。
表示韵韵的遥控车可以花t秒从第a个计时点到第b个计时点。
接下来m行每行2个整数u、v,意义如描述所示。
输出格式
第一行输出一个正整数,表示能参加的赛段数。
第二行输出一个正整数,表示总用时。
限制
各个测试点1s
提示
第一个计时点的高度是最高的;
u≠v;
对于50%的数据 n≤1000 m≤1000;
对于100%的数据 n≤10000 m≤100000;
答案小于2^64。
LCA,只用记录下deep就可以了,LCA判断x和y的公共祖先是否为x或y若是的话加上时间即可。
1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<cstring>
5 using namespace std;
6 const int maxn=10005;
7 int fa[maxn][20],deep[maxn];
8 int head[maxn],nextn[maxn],tov[maxn],w[maxn];
9 int pd[maxn];
10 int n,m,tot;int d[maxn];
11 long long t,ans;
12 void go(int x,int y,int z)
13 {
14 tot++;
15 nextn[tot]=head[x];
16 head[x]=tot;
17 tov[tot]=y;
18 w[tot]=z;
19 }
20
21 void dfs(int x)
22 {
23 int v=head[x];
24 while(v)
25 {
26 if(pd[tov[v]]==false)
27 {
28 fa[tov[v]][0]=x;
29 deep[tov[v]]=deep[x]+1;
30 d[tov[v]]=d[x]+w[v];
31 pd[tov[v]]=true;
32 int ii=0,pos=x;
33 while(fa[pos][ii])
34 {
35 fa[tov[v]][ii+1]=fa[pos][ii];
36 pos=fa[pos][ii];
37 ii++;
38 }
39 dfs(tov[v]);
40 }
41 v=nextn[v];
42 }
43 }
44 void lca(int x,int y)
45 {
46 if(deep[x]>deep[y])return ;
47 int m=deep[y]-deep[x];
48 int ii=0;
49 int k=y;
50 while(m)
51 {
52 if(m&1)y=fa[y][ii];
53 m=(m>>1);
54 ii++;
55 }
56 if(x!=y)return ;
57 ans++;
58 t+=d[k]-d[x];
59 }
60 int main()
61 {
62 scanf("%d%d",&n,&m);
63 for(int i=1;i<=n-1;i++)
64 {
65 int x,y,z;
66 scanf("%d%d%d",&x,&y,&z);
67 go(x,y,z);
68 }
69 deep[1]=1;pd[1]=true;
70 dfs(1);
71 for(int i=1;i<=m;i++)
72 {
73 int x,y;
74 scanf("%d%d",&x,&y);
75 lca(x,y);
76 }
77 printf("%I64d\n",ans);
78 printf("%I64d\n",t);
79 return 0;
80 }