[暴力/LCA]JZOJ 1209 拉力赛

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。

分析

显然求路径长我们搞个树上前缀和即可

然后求能否到达,可用LCA(懒得打)用了时间戳法

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N=1e4+10;
ll a[N];
int st[N],ed[N];
int tm;
struct Edge {
    int u,v,nx;
    ll w;
}e[N];
int cnt,list[N];
int n,m;

void Add(int u,int v,ll w) {
    e[++cnt].u=u;e[cnt].v=v;e[cnt].w=w;e[cnt].nx=list[u];list[u]=cnt;
}

void Dfs(int u) {
    tm++;
    st[u]=tm;
    for (int i=list[u];i;i=e[i].nx) {
        a[e[i].v]=a[u]+e[i].w;
        Dfs(e[i].v);
    }
    tm++;
    ed[u]=tm;
}

int main() {
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n-1;i++) {
        int u,v;
        ll w;
        scanf("%d%d%lld",&u,&v,&w);
        Add(u,v,w);
    }
    Dfs(1);
    ll count=0,ans=0;
    for (int i=1;i<=m;i++) {
        int u,v;
        scanf("%d%d",&u,&v);
        if (st[u]<=st[v]&&ed[v]<=ed[u]) count++,ans+=a[v]-a[u];
    }
    printf("%lld
%lld
",count,ans);
}
View Code
在日渐沉没的世界里,我发现了你。
原文地址:https://www.cnblogs.com/mastervan/p/9699181.html