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


    E - Edge Deletion

    题目大意:

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

    思路:

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

    3 3
    1 2 2
    2 3 3
    1 3 5
    

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

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

    Code:
    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;
    }
    
  • 相关阅读:
    SDN课程阅读作业(2)
    2019 SDN上机第5次作业
    第05组 Alpha事后诸葛亮
    第05组 Alpha冲刺(4/4)
    2020-4-5助教一周小结
    2020-3-29助教一周小结
    2020-3-22助教一周小结
    2020-03-15助教一周小结
    2020-03-08助教一周小结
    第一次个人编程作业(个人实现)
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/16001580.html
Copyright © 2020-2023  润新知