代码随想录算法训练营day55 day57| 108.冗余连接 109.冗余连接II 53.寻宝

学习资料:https://www.programmercarl.com/kamacoder/0108.冗余连接.html#思路

图论
并查集
prim算法
kruskal算法

学习记录:
108.冗余连接

点击查看代码
# 并查集解法
class UnionFind:
    def __init__(self, size):
        self.parent = list(range(size+1))
    def find(self, u):
        if u == self.parent[u]:
            return u
        else:
            self.parent[u] = self.find(self.parent[u])
            return self.parent[u]
            
    def join(self, u, v):
        """将v->u这条边加入并查集"""
        u = self.find(u)
        v = self.find(v)
        if u != v:
            self.parent[v] = u
            
    def isSame(self, u, v):
        u = self.find(u)
        v = self.find(v)
        return u == v



# 实时更新冗余边,如果有多条,那就保留最后一个,也就是最新款
result = None
# 输入值
n = int(input())
# 调用类
uf = UnionFind(n)
# 继续输入剩余信息
for i in range(n):
    s, t = map(int, input().split())
    # 判断s和t是否同根
    if uf.isSame(s, t):
        result = str(s) + ' ' + str(t)+'\t'
    else:
        uf.join(s, t)
# 输出多余边的结果
print(result)
    

109.冗余连接2(三种情况;关注入度为2的节点)

点击查看代码
class UnionFind():
    def __init__(self, size):
        self.parent = list(range(size + 1))
        
    def find(self, u):
        if u == self.parent[u]:
            return u
        self.parent[u] = self.find(self.parent[u])
        return self.parent[u]
    
    def join(self, u, v):
        u = self.find(u)
        v = self.find(v)
        if u != v:
            self.parent[u] = v
            
    def isSame(self, u, v):
        return self.find(u) == self.find(v)
    
    def is_tree_after_remove_edge(self, edges, edge, n):
        # 创建一个新的 UnionFind 实例以避免状态污染
        temp_uf = UnionFind(n)
        for i in range(len(edges)):
            if i == edge:
                continue
            s, t = edges[i]
            if temp_uf.isSame(s, t):
                return False  # 存在环
            temp_uf.join(s, t)
        return True

    def get_remove_edge(self, edges):
        for s, t in edges:
            if self.isSame(s, t):
                print(s, t)
                return
            else:
                self.join(s, t)


# 输入值
n = int(input())
uf = UnionFind(n)
edges = []
indegree = {}

# 输入边的信息并统计入度
for _ in range(n):
    s, t = map(int, input().split())
    indegree[t] = indegree.get(t, 0) + 1
    edges.append([s, t])

# 找入度为2的节点,记录下标
vec = []
for i in range(n - 1, -1, -1):
    if indegree[edges[i][1]] == 2:
        vec.append(i)

# 输出结果
if len(vec) > 0:
    # 情况一:删除靠后的边
    if uf.is_tree_after_remove_edge(edges, vec[0], n):
        print(edges[vec[0]][0], edges[vec[0]][1])
    # 情况二:只能删除特定的边
    else:
        print(edges[vec[1]][0], edges[vec[1]][1])
else:
    # 情况三:原图有环
    uf.get_remove_edge(edges)

53.寻宝(两种方法)

点击查看代码
# kruskal算法:关注边的算法。找到最短的边,如果对应的这条边的两个节点不在同一个集合,就把边加入生成树,把两个节点加入同一个集合
class Edge:
    def __init__(self, l, r, val):
        # 边的左节点和右节点和权值
        self.l = l
        self.r = r
        self.val = val

n = 10001
father = list(range(n))
def init():
    global father
    father = list(range(n))

def find(u):
    if u!=father[u]:
        father[u] = find(father[u])
    return father[u]
def join(u, v):
    u = find(u)
    v = find(v)
    if u!=v:
        father[v] = u
def kruskal(v, edges):
    edges.sort(key=lambda edge: edge.val)
    init()
    result_val = 0
    for edge in edges:
        x = find(edge.l)
        y = find(edge.r)
        if x!=y:
            result_val += edge.val
            join(x, y)
    return result_val

if __name__ == "__main__":
    # 输入值
    v, e = map(int, input().split())
    edges = []
    for _ in range(e):
        v1, v2, val = map(int, input().split())
        edges.append(Edge(v1, v2, val))
    result_val = kruskal(v, edges)
    print(result_val)
    
    

# # grim法:关注节点。三大步,选中距离生成树最近的节点;将该节点加入生成树;更新其余非生成树节点到生成树的最小距离
# # 输入值
# v, e = map(int, input().split())
# # 把剩余地图信息加入邻接矩阵,每个节点都初始化为10001,输入值用于存储两边的权值
# grid = [[10001] *(v+1) for _ in range(v+1)]
# for _ in range(e):
#     x, y, w = map(int, input().split())
#     # 点1到点2和点2到点1的距离一样,双向
#     grid[x][y] = w
#     grid[y][x] = w
    
# # 定义一个数组,用于保存该节点是否加入生成树中
# visited = [False]*(v+1)
# # 定义一个数组用于记录每个点距离生成树的最近距离,初始设置为10001
# minDist = [10001] * (v+1)

# # 按题目要求n个点,只需要n-1条边
# for _ in range(1, v+1):
#     min_val = 10002
#     cur = -1
#     for j in range(1, v+1):
#         if visited[j]==False and minDist[j] < min_val:
#             cur = j
#             min_val = minDist[j]
#     visited[cur] = True
#     for j in range(1, v+1):
#         if visited[j]==False and minDist[j]>grid[cur][j]:
#             minDist[j]=grid[cur][j]
# ans = 0
# for i in range(2, v+1):
#     ans += minDist[i]
# print(ans)

PS:今天好冷,阴转多云。拖了两天的内容,赶紧补上,好累,根本看不懂,不想看,都是抄的,下次回来再学
周末吃了黄焖鸡、圆子汤,今天吃了羊肉汤。
好不爽好烦!!!!平等的讨厌每个人!!!!第一次这么讨厌周日!!!! 烦死了
其实还是很伤心,怀念哥哥的一天
倒计时一周

posted @   Tristan241001  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示