AcWing 340. 通信线路
题目传送门:340. 通信线路 - AcWing题库
题目大致意思
对于一条路径,他的花费是,其经过的所以路线中花费最大的一条,你可以选择k条线,使其变为免费,求1到n的最小花费。
解题方法
本题可以用spfa加上dp来写。
对于同样是单源最短路,不可以用dijkstra的原因是:该题会将路径更改为0,如果用dijstra是不能更新已经确定的点,所以不可以使用。
为了做到更新点,我们使用队列优化的spfa。
我们知道普通的spfa是对于每一个点,扫描一边所以的边,但是队列优化的spfa是当影响该边的上一条边被更新,然后才更新该边,这样就不用扫描所有的边。
根据题意,我们可以用dp来表示费用,dp[x][p]表示从1~x,我们使用了p次免费的花费。如果有一条边x到y,花费为z加入,那么dp[y][p] = max(dp[x][p], z)。
接下来就是dp的公式,对于一条边,我们可以选择原价买下和让其免费。
那么我们可以得到dp[y][p] = min(dp[x][p - 1], max(dp[x][p], z))。其中dp[x][p-1]表示使用免费,max(dp[x][p], z)表示不使用免费。
AC代码:
#include <bits/stdc++.h> using namespace std; int ne[10010 * 2], e[10010 * 2], w[10010 * 2], h[1010], idx; int dp[1010][1010]; int sta[1010]; int n, p, k; void add(int x, int y, int z) // 邻接表建图 { e[idx] = y; w[idx] = z; ne[idx] = h[x]; h[x] = idx++; } void spfa() { queue<int> q; q.push(1); dp[1][0] = 0; sta[1] = 1; while (!q.empty()) { int x = q.front(); q.pop(); sta[x] = 0; for (int i = h[x]; i != -1; i = ne[i]) { int y = e[i], z = max(dp[x][0], w[i]); // 对于p = 0时 if (dp[y][0] > z) { dp[y][0] = z; if (sta[y] == 0) { sta[y] = 1; q.push(y); } } for (int p = 1; p <= k; p++) // 对于p > 0时 { z = min(dp[x][p - 1], max(dp[x][p], w[i])); if (dp[y][p] > z) { dp[y][p] = z; if (sta[y] == 0) { sta[y] = 1; q.push(y); } } } } } } void solve() { cin >> n >> p >> k; for (int i = 1; i <= n; i++) h[i] = -1; memset(dp, 0x3f, sizeof(dp)); for (int i = 1; i <= p; i++) { int x, y, z; cin >> x >> y >> z; add(x, y, z); add(y, x, z); } spfa(); int ans = 1e9; for (int i = 0; i <= k; i++) ans = min(dp[n][i], ans); if (ans == 1e9) cout << -1 << endl; else cout << ans << endl; return; } signed main() { int _; // cin >> _; _ = 1; while (_--) { solve(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!