Skip to content

课堂计划

P3416 [USACO16DEC] Moocast S

https://usaco.org/index.php?page=viewproblem2&cpid=668

约翰农场主的 $N$ 头奶牛需要建立一个广播系统,每头奶牛有一个对讲机,具有一定的传输半径 $P$。一头奶牛可以通过直接或中继的方式,将信息传递给其他奶牛。目标是找到从某头奶牛开始广播时,能够到达的奶牛的最大数量。

算法分析

  1. 图的构建
  2. 每头奶牛看作一个节点。
  3. 如果奶牛 $i$ 的对讲机能直接覆盖奶牛 $j$,则在图中从 $i$ 到 $j$ 添加一条有向边。

  4. 广度优先搜索 (BFS)

  5. 从每个节点开始,使用 BFS 遍历可达的所有节点。
  6. 记录从某个节点开始可以到达的最大节点数。

代码注释

# 读取奶牛数量
n = int(input())

# 初始化邻接表,用于存储每头奶牛可以直接发送信息到达的奶牛
e = [[] for _ in range(n)]

# 初始化位置和能量列表
pos, p = [], []

# 读取每头奶牛的位置和能量
for _ in range(n):
    x1, y1, p1 = map(int, input().split())
    pos.append((x1, y1))
    p.append(p1)

# 计算两头奶牛之间的距离平方
def dis(a, b):
    return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2

# 构建图,确定每头奶牛可以直接向哪些奶牛发送信息
for i in range(n): 
    for j in range(n):
        if i == j: continue  # 跳过自己
        # 如果奶牛 j 在奶牛 i 的传输范围内,则添加到邻接表
        if dis(pos[i], pos[j]) <= p[i] ** 2:
            e[i].append(j)

from collections import deque

# 初始化最大可到达奶牛数量
ans = 0

# 对每头奶牛执行广度优先搜索(BFS)
for i in range(n):
    # 用于记录访问过的奶牛
    vis = [False] * n
    # 创建队列进行 BFS
    q = deque()
    q.append(i)
    tot = 0
    vis[i] = True
    while len(q) > 0:
        tot += 1
        u = q.popleft()
        # 遍历当前奶牛可以直接到达的奶牛
        for v in e[u]:
            if not vis[v]:  # 如果奶牛 v 未访问过
                q.append(v)
                vis[v] = True
    # 更新最大可到达奶牛数量
    if tot > ans:
        ans = tot

# 输出最大可到达奶牛数量
print(ans)

程序填空版

n = int(input())
e = [[] for _ in range(n)]
pos, p = [], []

for _ in range(n):
    x1, y1, p1 = map(int, input().split())
    pos.append((x1, y1))
    p.append(p1)

def dis(a, b):
    # 计算两头奶牛之间的距离平方
    return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2

for i in range(n): 
    for j in range(n):
        if i == j: continue
        # 如果奶牛 j 在奶牛 i 的传输范围内,则添加到邻接表
        if dis(pos[i], pos[j]) <= ________:
            e[i].append(j)

from collections import ________
ans = 0

for i in range(n):
    # 用于记录访问过的奶牛
    vis = [False] * n
    # 创建队列进行 BFS
    q = deque()
    q.append(i)
    tot = 0
    vis[i] = ________

    while len(q) > 0:
        tot += 1
        u = q.________()
        # 遍历当前奶牛可以直接到达的奶牛
        for v in e[u]:
            if not vis[v]:
                q.append(v)
                vis[v] = ________

    # 更新最大可到达奶牛数量
    if tot > ans:
        ans = tot

# 输出最大可到达奶牛数量
print(______)

该算法使用图的表示和 BFS 来计算每头奶牛作为起点时,最多可以到达多少头奶牛。通过遍历每个节点并执行 BFS,我们可以找到最大的可达节点数。复杂度主要受 BFS 和图的构建影响,为 $O(N^2)$。

P6111 [USACO18JAN] MooTube S

https://usaco.org/index.php?page=viewproblem2&cpid=788

树的性质:

由于是树形结构,任意两个节点之间有且仅有一条路径。 任意两个视频间的相关性是路径上所有边中相关性最小的那一条。 解题思路 深度优先搜索 (DFS): 我们可以从给定的视频节点出发,使用 DFS 遍历整棵树。 在遍历过程中,只访问那些与当前节点相关性大于等于 K 的节点。 计数满足条件的节点。

def dfs(u, fa, k):
    global cnt
    # 遍历当前节点 u 的所有邻接节点
    for v, w in G[u]:
        # 如果该节点不是父节点且相关性 w 大于等于 k
        if v != fa and w >= k:
            cnt += 1  # 满足条件的节点计数加一
            dfs(v, u, k)  # 递归调用 DFS

import sys
# 增加递归深度限制,确保 DFS 不会因深度过大而失败
sys.setrecursionlimit(10000)

n, Q = map(int, input().split())
G = [[] for _ in range(n + 1)]  # 初始化邻接表

# 读取 N-1 条边的信息
for _ in range(n - 1):
    p, q, r = map(int, input().split())
    G[p].append((q, r))  # 添加边 p -> q
    G[q].append((p, r))  # 添加边 q -> p (无向图)

# 处理每个查询
for _ in range(Q):
    k, v = map(int, input().split())
    cnt = 0  # 初始化计数
    dfs(v, -1, k)  # 从节点 v 开始 DFS,父节点设为 -1 表示无父节点
    print(cnt)  # 输出满足条件的视频数量

填空:

def dfs(u, fa, k):
    global cnt
    # 遍历当前节点 u 的所有邻接节点
    for v, w in G[u]:
        # 如果该节点不是父节点且相关性 w 大于等于 k
        if ___ and ___:
            cnt += 1  # 满足条件的节点计数加一
            dfs(___)  # 递归调用 DFS

import sys
# 增加递归深度限制,确保 DFS 不会因深度过大而失败
sys.setrecursionlimit(10000)

n, Q = map(int, input().split())
G = [[] for _ in range(___)]  # 初始化邻接表

# 读取 N-1 条边的信息
for _ in range(n - 1):
    p, q, r = map(int, input().split())
    G[p].append((q, r))  # 添加边 p -> q
    G[q].append((___, ___))  # 添加边 q -> p (无向图)

# 处理每个查询
for _ in range(Q):
    k, v = map(int, input().split())
    cnt = ___  # 初始化计数
    dfs(v, ___, k)  # 从节点 v 开始 DFS,父节点设为 -1 表示无父节点
    print(___)  # 输出满足条件的视频数量

作业题 # P2997 [USACO10NOV] Banner S

https://www.luogu.com.cn/problem/P2997

平面上有(0,0)到(n,m)的(n+1)*(m+1)个点。问有多少点对所连的线段不过其他点,且长度在[l,h]范围内

枚举 dx, dy, dx 与 dy 互质即可。