LC1761 一个图中连通三元组的最小度数

发布时间 2023-08-31 20:06:40作者: yxu0528

一项三元环枚举技术。

整体思路是枚举三元环,其度数为 \(deg_i+deg_j+deg_k-6\) 再取 \(\min\)。全部的复杂度集中在枚举三元环上。

方法一: 枚举三个点,检查其是否成环。采用哈希表记录边的情况下,复杂度为 \(O(n^3)\)

方法二: 从边的角度考虑。对于无向边 \((i,j)\),改为指向度数大的点的有向边(相同度数则指向编号大的)。枚举点 \(i\) 和与 \(i\) 相连的点 \(j\),因为有 \(m\) 条边,这一步复杂度为 \(O(m)\);枚举点 \(j\) 的出边,可以证明不会超过 \(\sqrt{2m}\) 条边,所以这一步复杂度为 \(m\sqrt{m}\)

证明如下:假设 \(i\) 的出边为大于 \(\sqrt{2m}\),则原始无向图中 \(i\) 的度数大于 \(\sqrt{2m}\),则 \(i\) 指向的 \(\sqrt{2m}\)\(j\) 的度数也大于 \(\sqrt{2m}\),总度数大于 \(2m\),但总度数应该等于 \(2m\),矛盾。

golang 的 map 的 key 必须是定义了相等/不等的类型,这里的 []int 就不符合要求,但是可以对于定义成 []map[int]struct{}

方法一的 AC 代码:

func minTrioDegree(n int, edges [][]int) int {
    deg := make([]int, n)
    g := make([][]int, n)
    for i := 0; i < n; i++ {
        g[i] = make([]int, n)
    }
    for _, edge := range edges {
        u := edge[0] - 1
        v := edge[1] - 1
        deg[u]++; deg[v]++
        g[u][v], g[v][u] = 1, 1
    }
    ans := 0x3f3f3f3f
    for _, edge := range edges {
        u := edge[0] - 1
        v := edge[1] - 1
        for i := 0; i < n; i++ {
            if g[i][u] == 1 && g[i][v] == 1 {
                ans = min(ans, deg[i] + deg[u] + deg[v] - 6)
            }
        }
    }
    if ans == 0x3f3f3f3f {
        return -1
    }
    return ans
}

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

THE END