题解 | 2019牛客国庆集训派对 H-Highway
Highway
https://ac.nowcoder.com/acm/contest/1109/H
title: 2019牛客国庆集训派对 H-Highway (dijk求树的直径(当然还有更优的))
categories: 2019牛客国庆集训派对
top: false
tags:
acm
树的直径
题目大意
n个点从1-n, 有(n - 1)条边连接。
现在要重新修(n - 1)条路, 修i 到 j 所用的代价为i到j的最短路,
问最多的代价是多少
分析
就是求树的直径, 然后跑两边最短路求其他点到直径两端点的最短路, 最后把最大值加起来就可。
AC代码
#include using namespace std; typedef long long ll; typedef pair P; const int INF = 0x3f3f3f3f; const ll llINF = 0x3f3f3f3f3f3f3f3f; const int mod = int(1e9) + 7; const int N = int(1e5) + 10; struct edge{ int u, v, ne; ll w; }ed[2 * N]; int n, cnt, head[N]; ll dis1[N], dis2[N]; bool vis[N]; void init(){ cnt = 0; memset(head, -1, sizeof head); } void add(int u, int v, ll w){ ed[cnt].u = u, ed[cnt].v = v, ed[cnt].w = w, ed[cnt].ne = head[u]; head[u] = cnt++; } int dijk(ll dis[], int st){ for (int i = 1; i <= n; i++) dis[i] = ll(1e15); memset(vis, false, sizeof vis); priority_queue, greater >q; dis[st] = 0; q.emplace(0, st); while(!q.empty()){ int u = q.top().second; q.pop(); if (vis[u]) continue; vis[u] = 1; for (int i = head[u]; ~i; i = ed[i].ne){ int v = ed[i].v; if (dis[v] > dis[u] + ed[i].w){ dis[v] = dis[u] + ed[i].w; q.emplace(dis[v], v); } } } ll ans = 0, ansj; for (int i = 1; i <= n; ++i){ if (dis[i] != ll(1e15) && dis[i] > ans){ ans = dis[i], ansj = i; } } return ansj; } int main() { std::ios::sync_with_stdio(0); int a, b; ll c; while(cin >> n){ init(); for (int i = 0; i < n - 1; ++i){ cin >> a >> b >> c; add(a, b, c); add(b, a, c); } int s1 = dijk(dis1, 1); int s2 = dijk(dis1, s1); dijk(dis1, s1); dijk(dis2, s2); ll ans = dis1[s2]; for (int i = 1; i <= n; i++){ if (i == s1 || i == s2) continue; ans += max(dis1[i], dis2[i]); } cout << ans <<"\n"; } return 0; } 、
恰似你一低头的温柔,娇弱水莲花不胜寒风的娇羞, 我的心为你悸动不休。 --mingfuyan