• 最小环


    oi-wiki上讲得极好:(链接)

    问题

    图上找一大小至少为3的环,要求最小化环上边权和。

    解法

    Dijkstra

    枚举环上一条边 ((u, v)),删掉它,然后跑Dij,用距离 + (val[u][v]),取最小值即可。

    复杂度:(O(m(n+m)logn))

    Floyd

    如果 (m = n^2),那么Dij就会造成 (O(n^4logn)) 的复杂度。因此我们需要一个更跟 (n) 有关的算法。

    还是上 oi-wiki 吧。

    记原图中 u, v 之间边的边权为 val(u, v) 。
    
    我们注意到 Floyd 算法有一个性质:在最外层循环到点 k 时(尚未开始第 k 次循环),最短路数组 dis 中, dis[u][v] 表示的是从 u 到 v 且仅经过编号在 [1,k) 区间中的点的最短路。
    
    由最小环的定义可知其至少有三个顶点,设其中编号最大的顶点为 w ,环上与 w 相邻两侧的两个点为 u, v ,则在最外层循环枚举到 k = w 时,该环的长度即为  dis[u][v] + val[w][u] + val[v][w]。
    
    故在循环时对于每个 k 枚举满足 i < k, j < k 的 (i, j) ,更新答案即可。
    
    时间复杂度: O(n^3)
    

    附上我的代码。(有向图边权为1的最小环)

    for (register int i = 1; i <= m; ++i) {
        for (register int j = 1; j <= m; ++j) {
            if (e[i][j])    dis[i][j] = 1;
            else    dis[i][j] = inf;
        }
    }
    int ans = inf;
    for (register int k = 1; k <= m; ++k) {
        for (register int i = 1; i < k; ++i) {
            for (register int j = 1; j < k; ++j) if (j != i) {
                if (e[k][i] && e[j][k]) {
                    MIN(ans, dis[i][j] + 2);
                }
            }
       }
       for (register int i = 1; i <= m; ++i) if (dis[i][k] < inf) {
           for (register int j = 1; j <= m; ++j) if (j != i) {
                MIN(dis[i][j], dis[i][k] + dis[k][j]);
           }
        }
    }
    

    例题:

    hdu 6080 度度熊保护村庄

    计算几何+最小环。

  • 相关阅读:
    160-三个用户同时登录,是怎么实现多线程的?
    159-如何解决缓存穿透?
    158-为什么会引发缓存穿透?
    存储emoji表情,修改字符集为utf8mb4
    java相差小时数
    pom.xml解释
    前端 跨域
    java 获取的是本地的IP地址
    是否超时
    发送验证码
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13293775.html
Copyright © 2020-2023  润新知