题意:
给定三个整数n,m,k,分别表示图中的点数、边数、最大保留边数。问在最多保留k条边的情况下,怎样删除边能确保剩下没有删除的点到起点的距离是最短边。
题解:
题目的意思就是问最多有多少个点在删除其他点的情况下,从起点到这个点的最短距离不变。用Dijkstra的堆优化就可解决,依次取到起点最近的点,直到取了k个点或者队列为空就停止。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define ve vector
#define rep(i, a, b) for (int i = a; i < b; i++)
using i64 = long long;
using pl = pair<i64, pair<int, int>>;
inline int read() {
int x;
cin >> x;
return x;
}
void solve() {
int n = read(), m = read(), k = read();
ve<ve<pl>> g(n + 1);
ve<i64> dis(n + 1, 1e15);
ve<int> res;
rep(i, 1, m + 1) {
int l = read(), r = read(), w = read();
g[l].push_back({w, {i, r}});
g[r].push_back({w, {i, l}});
}
priority_queue<pl, ve<pl>, greater<pl>> q;
dis[1] = 0;
q.push({0, {0, 1}});
while(q.size() && int(res.size()) <= k) {
auto [d, v] = q.top();
q.pop();
if (dis[v.se] != d) {
continue;
}
res.emplace_back(v.fi);
for (auto [t, u] : g[v.se]) {
int j = u.se;
if (dis[j] > dis[v.se] + t) {
dis[j] = dis[v.se] + t;
q.push({dis[j], {u.fi, j}});
}
}
}
int len = res.size();
cout << len - 1 << '\n';
rep(i, 1, len) {
cout << res[i] << " \n"[i == len - 1];
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
while(t--) {
solve();
}
}