jzoj1209. 拉力賽(dfs序)
阿新 • • 發佈:2018-12-11
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
Hint 【資料規模和約定】 第一個計時點的高度是最高的; u≠v; 對於50%的資料 n≤1000 m≤1000; 對於100%的資料 n≤10000 m≤100000; 答案小於2^64。
程式碼
#include <cstdio> #define N 100005 #define ll long long using namespace std; struct arr { int nxt, to, w; }a[N]; int l, ls[N], k; int n,m,fa[N],dfn[N],siz[N]; ll tim[N], f[10005][500]; void add(int x, int y, int z) { a[++l].to = y; a[l].nxt = ls[x]; a[l].w = z; ls[x] = l; } void dfs(int x, int y, ll t1) { fa[x] = y; tim[x] = t1; dfn[x] = ++k; siz[x] = 1; for (int i = ls[x]; i; i = a[i].nxt) if (a[i].to != fa[x]) { dfs(a[i].to, x, t1 + a[i].w); siz[x] += siz[a[i].to]; } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i < n; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); add(x, y, z); add(y, x, z); } dfs(1, 0, 0); ll ans = 0; ll t = 0; for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); if ((dfn[y] > dfn[x] + siz[x] - 1) || (dfn[y] < dfn[x])) continue; ans++; if (x == y) continue; t += tim[y] - tim[x]; } printf("%d\n", ans); printf("%lld", t); }