Description
车展结束后,游乐园决定举办一次盛大的山道拉力赛,平平和韵韵自然也要来参加大赛。
赛场上共有n个连通的计时点,n-1条赛道(构成了一棵树)。每个计时点的高度都不相同(父结点的高度必然大于子结点),相邻计时点间由赛道相连。由于马力不够,所以韵韵的遥控车只能从高处驶向低处。而且韵韵的车跑完每条赛道都需花费一定的时间。
举办方共拟举办m个赛段的比赛,每次从第u个计时点到第v个计时点,当然其中有不少比赛韵韵的遥控车是不能参加的(因为要上坡)。平平想知道他能参加多少个赛段的比赛,并且想知道他完成这些赛段的总用时。
Input
第一行两个整数n,m。
接下来n-1行每行3个整数a、b、t。
表示韵韵的遥控车可以花t秒从第a个计时点到第b个计时点。
接下来m行每行2个整数u、v,意义如描述所示。
Output
第一行输出一个正整数,表示能参加的赛段数。
第二行输出一个正整数,表示总用时。
Sample Input
6 2
1 2 1
2 4 1
2 5 1
5 6 1
1 3 1
2 6
4 5
Sample Output
1
2
Data Constraint
Hint
【数据规模和约定】
第一个计时点的高度是最高的;
u≠v;
对于50%的数据 n≤1000 m≤1000;
对于100%的数据 n≤10000 m≤100000;
答案小于2^64。
思路
这题其实就一个dfs
对图进行一次dfs,记录每个点第一次被访问到的时间戳begin[i]和完成以这个点围根的树的时间戳finish[i]。则u是v的祖先的充要条件是Begin[u]<begin[v]且finish[v]<finish[u]
当然听说LCA也行
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int maxn=10077;
int n,m,step,cnt,list[maxn],tot;
ll ans;
struct A
{
int x,y;
ll t;
}a[maxn];
struct E
{
int to,next;
ll v;
}e[maxn*2];
void add(int u,int v,ll val)
{
e[++cnt].to=v; e[cnt].next=list[u]; list[u]=cnt; e[cnt].v=val;
}
void dfs(int u,int fa)
{
a[u].x=step;
for(int i=list[u]; i; i=e[i].next)
{
int v=e[i].to;
if(v==fa) continue;
step++; a[v].t+=a[u].t;
dfs(v,u);
}
a[u].y=step;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n-1; i++)
{
ll t;
int x,y;
scanf("%d%d%lld",&x,&y,&t); add(x,y,t);
a[y].t=t;
}
step=1;
dfs(1,0);
for(int i=1; i<=m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(a[x].x<=a[y].x&&a[y].x<=a[x].y) tot++,ans+=a[y].t-a[x].t;
}
printf("%d\n%lld",tot,ans);
}