P15818 [JOI 2015 Final] JOI 公园 / JOI Park
题目解析
直接上代码,你绝对看得懂!
// 地道被我写成了通道,看得懂就好
#include <bits/stdc++.h>
using namespace std;
#define int long long
constexpr int N = 1e5 + 2;
vector<pair<int, int>> a[N];
bool f[N], u[N];
int d[N];
pair<int, int> b[N];
inline void dij() { // 板子
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
memset(d, 127, sizeof d);
d[1] = 0;
q.push({0, 1});
while (!q.empty()) {
auto t = q.top();
q.pop();
int now = t.second;
if (d[now] < t.first) continue;
if (f[now]) continue;
f[now] = true;
for (auto i : a[now]) {
int x = i.first, y = i.second;
if (d[now] + y < d[x]) {
d[x] = d[now] + y;
q.push({d[x], x});
}
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n, m, c;
cin >> n >> m >> c;
int tot = 0; // 所有边权总和,在后面是没进入通道的边权总和
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
a[u].push_back({v, w});
a[v].push_back({u, w});
tot += w;
}
dij();
for (int i = 1; i <= n; i++) {
b[i] = {d[i], i}; // 为了排序,x小的点一定会先一步有通道,随着x的增大这些始终在通道里
}
sort(b + 1, b + n + 1);
int ans = tot;
for (int i = 1; i <= n; i++) {
int sy = b[i].second;
u[sy] = true;
for (auto e : a[sy]) {
if (u[e.first]) {
// 如果sy和e.first都和和通道接触的点,那么他们的道路就可以拆掉,因为加入了通道
tot -= e.second; // 在通道里
}
}
ans = min(ans, tot + c * b[i].first); // 更新最小花费
}
cout << ans;
// for (int i = 1; i <= n; i++) {
// cout << d[i] << " ";
// }
}
别忘了点赞

浙公网安备 33010602011771号