AtCoder Beginner Contest 243 E - Edge Deletion(最短路)

E - Edge Deletion

题目大意:

给出 n(n300) 个节点的无向图联通图,问最多可以删除多少条边,使得删除后的图,对于任意两个节点 uv 其最短路都没有发生改变。

思路:

赛时以为是求 n 遍最短路,标记所有最短路上的边,然后剩下的就是可以删的,但是这样删很有可能删多了,也处理不了这样的情况:

Copy
3 3 1 2 2 2 3 3 1 3 5

还是考虑松弛操作,对于一条边 [u,v] 来说,如果它被松弛了,则说明这条边不是最短路上的边,不需要留下,因为可以经过其他更短的边从 u 到达 v

这题的 n 很小,我们可以使用 floyd 求出任意两点的最短路,然后枚举边判断该边是否被松弛过,累计可以删除的边。

Code:
Copy
struct Edge { int u, v, w; }; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, m; cin >> n >> m; vector<vector<int>> g(n + 1, vector<int>(n + 1, INF)); for (int i = 1; i <= n; i++) { g[i][i] = 0; } vector<Edge> e(m); for (int i = 0; i < m; i++) { cin >> e[i].u >> e[i].v >> e[i].w; g[e[i].u][e[i].v] = g[e[i].v][e[i].u] = e[i].w; } for (int k = 1; k <= n; k++) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { ckmin(g[i][j], g[i][k] + g[k][j]); } } } int cnt = 0; for (auto [u, v, w] : e) { bool ok = true; for (int k = 1; k <= n; k++) { if (k != u && k != v && g[u][v] >= g[u][k] + g[k][v]) { ok = false; } } cnt += ok; } cout << m - cnt << "\n"; return 0; }
posted @   Nepenthe8  阅读(158)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示