蓝桥杯-繁忙的都市

文章介绍了如何使用贪心策略对图中的边按长度排序并构建最小生成树,避免形成环。同时,也提及了Prim算法,通过不断更新节点与集合的距离找到最小生成树。
摘要由CSDN通过智能技术生成
"""
https://www.lanqiao.cn/problems/889/learning/?page=1&first_category_id=1&problem_id=889
"""
"""
贪心思路: 将所有的边按照边的长度从小到大排序, 每次取出最短的那条边, 
如果加入到生成树后不会成环就加入, 否则就改造(不要)这条路
"""
n, m = map(int, input().split())
# 使用普通列表存图
e = []
for _ in range(m):
    u, v, w = map(int, input().split())
    e.append((w, u, v))
# 1.将所有边按照边的长度从小到大进行排序
e.sort()

# p记录每个节点的祖宗节点
p = list(range(n + 1))
def find_root(x):
    if x != p[x]:
        p[x] = find_root(p[x])
    return p[x]

# 记录最大的那条路的分值
ans = 0
# 贪心: 每次取出的道路的分值都是最小的, 作出最佳的决策
for w, u, v in e:
    rootu = find_root(u)
    rootv = find_root(v)
    """
    u、v不属于同一集合, 则可以合并, 否则加入(u, v)这条边就会形成一个环。
    假设有3条路: (1, 2), (2, 3), (3, 1)
    遍历到第三条边的时候就会发现, 节点3和1指向同一个父亲, 形成2->1->3->2的环
    """
    if rootu != rootv:
        p[rootu] = rootv
        ans = max(ans, w)
# 最小生成树: 图的所有生成树中具有边上的权值之和最小的树称为图的最小生成树
# 改造后的道路就是一个最小生成树, 树的边数 = 节点数 - 1
print(n - 1, ans)

# 第二种: Prim算法

INF = 1e9
n, m = map(int, input().split())
Map = [[INF] * (n + 1) for _ in  range(n + 1)]
for _ in range(m):
    u, v, w = map(int, input().split())
    # u和v之间可能有多条路, 取其中最短的
    Map[u][v] = Map[v][u] = min(Map[u][v], w) 

# 1.最开始的起始点
u = 1
# d[i]表示点i离集合的距离
d = [INF] * (n + 1)
# 记录最大的那条路的分值
ans = 0
# 2.不断利用起始点u更新d数组, 进行n - 1次循环
for i in range(n - 1):
    # 起始点u到集和距离为0
    d[u] = 0
    # 2.1.利用u更新d, 同时找出d最小的未加入集合的点
    next_u, next_val = 1, INF
    for v in range(1, n + 1):
        # d[v]==0表示点已经在集合中了, 所以与集合的距离为0
        if d[v] == 0:
            continue
        # 更新节点v与集合(或者起始点u)的距离
        d[v] = min(d[v], Map[u][v])
        # 找出未加入集合中与集合最近的点
        if d[v] < next_val:
            # 下一轮循环的起始点u
            next_u = v
            # 不断更新其他点与集合的最小距离
            next_val = d[v]
    ans = max(ans, next_val)
    u = next_u
# 最小生成树: 图的所有生成树中具有边上的权值之和最小的树称为图的最小生成树
# 改造后的道路就是一个最小生成树, 树的边数 = 节点数 - 1
print(n - 1, ans)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好无聊啊,烦死

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值