1. 程式人生 > >jzoj1209. 拉力賽(dfs序)

jzoj1209. 拉力賽(dfs序)

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);
}