leetcode每日刷题

leetcode2959

2959. 关闭分部的可行集合数目 - 力扣(LeetCode)

不会做,照着灵神把代码敲了一遍+ai理解

g = [[inf] * n for _ in range(n)]

初始化一个 `n` x `n` 的图的邻接矩阵 `g`,所有元素设为无穷大(`inf`),表示在没有道路连接的情况下,节点间的距离是无穷的。

for x, y, wt in roads:

遍历输入的 `roads` 列表,每次迭代得到一条道路的起点 `x`、终点 `y` 和权重 `wt`。

            g[x][y] = min(g[x][y], wt)
            g[y][x] = min(g[y][x], wt)

更新邻接矩阵 `g`,将起点到终点的权重设置为当前值和新权重 `wt` 中的较小者,同时因为是无向图,也要更新终点到起点的权重。

 ans = 1  # s=0 一定满足要求

初始化答案变量 `ans` 为 1,因为状态 `s=0`(没有选择任何节点)总是满足要求。

        f = [[[inf] * n for _ in range(n)] for _ in range(1 << n)]

初始化一个三维数组 `f`,用于存储从状态 `s` 到任意两个节点 `i` 和 `j` 的最小距离。`1 << n` 表示所有可能的状态数(2的n次方)。
        f[0] = g
将 `f` 数组的第 0 个状态初始化为图的邻接矩阵 `g`。
遍历从 1 到 `2^n - 1` 的所有状态,每个状态 `s` 用二进制表示,每一位表示一个节点是否被选中。
            k = s.bit_length() - 1
计算状态 `s` 的二进制表示中最高位的索引 `k`。
            t = s ^ (1 << k)
计算状态 `s` 中除去最高位后的状态 `t`。
            ok = 1
初始化一个标志变量 `ok`,用于检查当前状态 `s` 是否满足所有节点对的最大距离限制。
            for i in range(n):
                for j in range(n):
嵌套循环遍历所有节点对 `(i, j)`。
                    f[s][i][j] = min(f[t][i][j], f[t][i][k] + f[t][k][j])
对于当前状态 `s`,更新节点 `i` 到 `j` 的最小距离,取状态 `t` 下的直接距离或通过节点 `k` 的间接距离的较小者。
                    if ok and j < i and s >> i & 1 and s >> j & 1 and f[s][i][j] > maxDistance:
                        ok = 0
如果当前状态 `s` 仍然有效(`ok` 为 1),并且节点对 `(i, j)` 满足以下条件:
- `j < i`:确保不会重复计算同一对节点。
- `s >> i & 1` 和 `s >> j & 1`:检查节点 `i` 和 `j` 在状态 `s` 中是否都被选中。
- `f[s][i][j] > maxDistance`:节点对 `(i, j)` 的距离是否超过了最大距离限制。
如果这些条件都满足,且节点对的距离超过了限制,则将 `ok` 设置为 0,表示当前状态不满足要求。
            ans += ok

如果当前状态 `s` 满足所有要求(`ok` 为 1),则将答案 `ans` 加一。
        return ans
返回满足条件的集合数量。

class Solution:
    def numberOfSets(self, n: int, maxDistance: int, roads: List[List[int]]) -> int:
        g = [[inf] * n for _ in range(n)]
        for x, y, wt in roads:
            g[x][y] = min(g[x][y], wt)
            g[y][x] = min(g[y][x], wt)

        ans = 1  # s=0 一定满足要求
        f = [[[inf] * n for _ in range(n)] for _ in range(1 << n)]
        f[0] = g
        for s in range(1, 1 << n):
            k = s.bit_length() - 1
            t = s ^ (1 << k)
            ok = 1
            for i in range(n):
                for j in range(n):
                    f[s][i][j] = min(f[t][i][j], f[t][i][k] + f[t][k][j])
                    if ok and j < i and s >> i & 1 and s >> j & 1 and f[s][i][j] > maxDistance:
                        ok = 0
            ans += ok
        return ans

leetcode1334

1334. 阈值距离内邻居最少的城市 - 力扣(LeetCode)

floyd算法

class Solution:
    def findTheCity(self, n: int, edges: List[List[int]], distanceThreshold: int) -> int:
        ans = (inf,-1)
        grid = [[inf for _ in range(n)] for _ in range(n)]
        for u,v,w in edges:
            grid[u][v] = w
            grid[v][u] = w
        for start in range(n):
            grid[start][start] = 0
            for i in range(n):
                for j in range(n):
                    grid[i][j] = min(grid[i][j],grid[i][start] + grid[start][j])
        for i in range(n):
            cnt = sum(grid[i][j] <= distanceThreshold for j in range(n))
            if cnt <= ans[0]:
                ans = (cnt,i)
        return ans[1]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值