从0开始学算法——第十九天(并查集练习)

写在开头的话

学习了今天的基础知识,让我们来做几道题来练练手吧。(题目是别的地方扒来的,参考答案是我自己写的,肯定不是最优解,有更好的方法欢迎评论区交流)

第一题------并查集

第二题------岛屿的数量

第三题------连通块中点的数量

参考答案

第一题参考答案(Python版)

python 复制代码
import sys
sys.setrecursionlimit(1000000)

def main():
    data = sys.stdin.read().strip().split()
    n, m = int(data[0]), int(data[1])
    parent = list(range(n + 1))
    rank = [0] * (n + 1)

    def find(x):
        while parent[x] != x:
            parent[x] = parent[parent[x]]
            x = parent[x]
        return x

    def union(x, y):
        root_x = find(x)
        root_y = find(y)
        if root_x == root_y:
            return
        if rank[root_x] < rank[root_y]:
            parent[root_x] = root_y
        elif rank[root_x] > rank[root_y]:
            parent[root_y] = root_x
        else:
            parent[root_y] = root_x
            rank[root_x] += 1

    idx = 2
    results = []
    for _ in range(m):
        op = data[idx]
        a = int(data[idx + 1])
        b = int(data[idx + 2])
        idx += 3
        if op == 'M':
            union(a, b)
        elif op == 'Q':
            if find(a) == find(b):
                results.append("Yes")
            else:
                results.append("No")

    sys.stdout.write("\n".join(results))

if __name__ == "__main__":
    main()

第二题参考答案(Python版)

python 复制代码
import sys

def main():
    sys.setrecursionlimit(1000000)
    
    # 读取输入
    n = int(sys.stdin.readline().strip())
    matrix = []
    for _ in range(n):
        row = list(map(int, sys.stdin.readline().split()))
        matrix.append(row)
    
    # 并查集初始化
    parent = list(range(n * n))
    rank = [0] * (n * n)
    
    def find(x):
        # 路径压缩
        if parent[x] != x:
            parent[x] = find(parent[x])
        return parent[x]
    
    def union(x, y):
        root_x = find(x)
        root_y = find(y)
        if root_x != root_y:
            # 按秩合并
            if rank[root_x] < rank[root_y]:
                parent[root_x] = root_y
            elif rank[root_x] > rank[root_y]:
                parent[root_y] = root_x
            else:
                parent[root_y] = root_x
                rank[root_x] += 1
    
    # 方向数组:上、下、左、右
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    
    # 遍历矩阵,合并相邻的陆地
    for i in range(n):
        for j in range(n):
            if matrix[i][j] == 1:
                index = i * n + j
                for di, dj in directions:
                    ni, nj = i + di, j + dj
                    # 检查相邻格子是否在矩阵内且为陆地
                    if 0 <= ni < n and 0 <= nj < n and matrix[ni][nj] == 1:
                        neighbor_index = ni * n + nj
                        union(index, neighbor_index)
    
    # 统计岛屿数量:收集所有陆地块的根节点
    roots = set()
    for i in range(n):
        for j in range(n):
            if matrix[i][j] == 1:
                roots.add(find(i * n + j))
    
    print(len(roots))

if __name__ == "__main__":
    main()

第三题参考答案(Python版)

python 复制代码
import sys
sys.setrecursionlimit(300000)

def find(x, parent):
    if parent[x] != x:
        parent[x] = find(parent[x], parent)
    return parent[x]

def union(a, b, parent, size):
    root_a = find(a, parent)
    root_b = find(b, parent)
    
    if root_a != root_b:
        if size[root_a] < size[root_b]:
            root_a, root_b = root_b, root_a
        parent[root_b] = root_a
        size[root_a] += size[root_b]

def main():
    import sys
    input = sys.stdin.read
    data = input().split()
    
    n = int(data[0])
    m = int(data[1])
    
    parent = list(range(n + 1))
    size = [1] * (n + 1)
    
    idx = 2
    results = []
    
    for _ in range(m):
        op = data[idx]
        idx += 1
        
        if op == 'C':  # Connect
            a = int(data[idx]); idx += 1
            b = int(data[idx]); idx += 1
            union(a, b, parent, size)
        
        elif op == 'Q1':  # Query 1
            a = int(data[idx]); idx += 1
            b = int(data[idx]); idx += 1
            root_a = find(a, parent)
            root_b = find(b, parent)
            results.append("Yes" if root_a == root_b else "No")
        
        elif op == 'Q2':  # Query 2
            a = int(data[idx]); idx += 1
            root_a = find(a, parent)
            results.append(str(size[root_a]))
    
    sys.stdout.write("\n".join(results))

if __name__ == "__main__":
    main()
相关推荐
AAA@峥1 小时前
系统化学习 MySQL:数据类型、库表管理、增删改查全解析
数据库·学习·mysql
神明不懂浪漫1 小时前
【第七章】Java中的常用类
java·开发语言·前端·经验分享·笔记
梓䈑5 小时前
【算法题攻略】BFS 解决FloodFill 算法、最短路问题、多源BFS 和 拓扑排序
c++·算法·宽度优先
Adios7948 小时前
设置交集大小至少为2
数据结构·算法·leetcode
GeekArch13 小时前
第28讲:避坑——AI堆栈分配错误、栈溢出BUG
c语言·人工智能·stm32·mcu·学习·bug
weixin_4280053014 小时前
C#调用 AI学习从0开始-第3阶段RAG向量数据库-文档切分与入库第15天
人工智能·学习·c#·向量数据库·rag·qdrant·文档切分与入库
来一碗刘肉面14 小时前
栈的应用(表达式求值)
数据结构·算法
xiaowang1234shs15 小时前
怪兽轻断食技术深度测评:从断食计时引擎到AI识别算法的工程实践解析
数据库·人工智能·算法·macos·机器学习·p2p·visual studio
小果因子实验室15 小时前
量化研究--策略迁移算法1研究
算法