吉林大學ACM集訓隊選拔賽(重現賽)I-Firework (最短路)

鏈接:https://ac.nowcoder.com/acm/contest/5944/I
來源:牛客網
 

題目描述

Alice and Bob get a strange firework accidentally, and they never know how to play it, so they come to you for help.

The firework consists of n nodes and n-1 fuses connecting pairs of nodes. The whole firework forms an undirected tree. At the time 0, several nodes are ignited simultaneously. After that, the fire begins to spread through the fuses to all directions from those nodes which has been ignited. When the fire reaches another node that haven't been ignited before, it will ignite the node and keep spreading.

Fire has a specific speed. If the fuse has the length L, it needs 2L seconds to conduct the fire. Then the question comes: how long it will take to burn up the firework? We consider that the firework is burned up if and only if all the fuses are burned up.

輸入描述:

The first line contains two integers n, m (1≤n,m≤105)(1\leq n,m\leq10^5)(1≤n,m≤105) -- the number of nodes of the firework and the number of nodes which are ignited initially.

This is followed by n-1 lines with fuse descriptions. Each fuse is given by three integers u, v and w (1≤u,v≤n,1≤w≤109)(1\leq u, v\leq n, 1\leq w \leq 10^9)(1≤u,v≤n,1≤w≤109), meaning that there is a fuse between node u and v with the length w.

The next line contains m distinct integers describing the ignited nodes' numbers.

輸出描述:

Only one line with a single number T --  the time it takes to burn up the firework.

示例1

輸入

複製3 2 1 2 1 2 3 2 1 3

3 2
1 2 1
2 3 2
1 3

輸出

複製3

3

說明

For the first example, the fire reaches node 2 from the fuse (1,2) in 2 seconds. But the fuse (2,3) is still burning, the final answer is 3 seconds.

示例2

輸入

複製5 2 1 2 5 2 3 1 2 4 2 4 5 1 1 4

5 2
1 2 5
2 3 1
2 4 2
4 5 1
1 4

輸出

複製7

7

題目大意:

一棵N(1e5)個點的帶邊權樹,你要在K個點同時點火,火每2單位時間可以燒一單位長度,問你把所有的邊燒完需要多長時間。

解法:

不難看出每條邊有且僅有兩個着火點靠近,所以求出每條邊的兩端着火時間,將K個點加進隊列,跑最短路的過程中記錄着火時間,最後判斷一下該邊是一頭燒完還是兩頭一起燒完,取所有邊燒完時間的最大值。

Accepted code

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;

#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 1e5 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }

struct node
{
	int id; ll w;
	bool operator < (const node &oth) const {
		return w > oth.w;
	}
};
vector <pir> G[N << 1];
vector <ll> vec[N];
ll dis[N], val[N];
bool vis[N];
int n, k;

void dijkstra() {
	priority_queue <node> q;
	MEM(dis, LINF);
	for (int i = 0; i < k; i++) {
		int t;
		sc("%d", &t);
		dis[t] = 0;
		q.push({ t, 0ll });   // 加入隊列
	}
	while (!q.empty()) {
		node now = q.top();
		q.pop();
		int u = now.id;
		if (vis[u])
			continue;
		vis[u] = true;

		for (auto it : G[u]) {
			int v = it.second, id = it.first;
			vec[id].push_back(dis[u]);           // 着火時間點
			if (dis[v] > dis[u] + val[id]) {
				dis[v] = dis[u] + val[id];
				q.push({ v, dis[v] });
			}
		}
	}
}

int main()
{
	cin >> n >> k;
	for (int i = 1; i < n; i++) {
		int u, v;
		sc("%d %d %lld", &u, &v, &val[i]);
		G[u].push_back({ i, v });
		G[v].push_back({ i, u });
	}
	dijkstra();

	ll ans = 0;
	for (int i = 1; i < n; i++) {
		ll l = vec[i][0], r = vec[i][1];
		ll w = val[i];
		if (l > r)
			swap(l, r);        // 兩端着火時間
		if (l + w <= r)           // 一頭燒完
			Max(ans, 2ll * (l + w));
		else                      // 兩頭一起燒完
			Max(ans, 2 * r + (l + w - r));
	}
	printf("%lld\n", ans);
	return 0;  // 改數組大小!!!用pair記得改宏定義!!!
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章