红色警报问题--python

一、问题引入

战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不改变其他城市之间的连通性,则不要发出警报。

输入格式:
输入在第一行给出两个整数N(0 < N ≤ 500)和M(≤ 5000),分别为城市个数(于是默认城市从0到N-1编号)和连接两城市的通路条数。随后M行,每行给出一条通路所连接的两个城市的编号,其间以1个空格分隔。在城市信息之后给出被攻占的信息,即一个正整数K和随后的K个被攻占的城市的编号。

注意:输入保证给出的被攻占的城市编号都是合法的且无重复,但并不保证给出的通路没有重复。

输出格式:
对每个被攻占的城市,如果它会改变整个国家的连通性,则输出Red Alert: City k is lost!,其中k是该城市的编号;否则只输出City k is lost.即可。如果该国失去了最后一个城市,则增加一行输出Game Over.。

输入样例:

5 4
0 1
1 3
3 0
0 4
5
1 2 0 4 3

输出样例:

City 1 is lost.
City 2 is lost.
Red Alert: City 0 is lost!
City 4 is lost.
City 3 is lost.
Game Over.

二、解决思路

在这里插入图片描述

1.构建图的邻接表:首先读取输入数据,构建表示城市间连接关系的邻接表。

2.计算初始连通分量:使用BFS或DFS遍历图,计算初始状态下国家的连通区域数量。

3.处理被攻占的城市:

•对于每个被攻占的城市,将其从图中"移除"(标记为已删除)

•重新计算当前连通区域数量

•比较新连通区域数量与之前数量的变化:

如果新数量 > 原数量+1:发出红色警报

如果新数量 > 原数量:发出红色警报

否则:只输出普通信息

•更新当前连通区域数量为新的数量

4.游戏结束判断:如果所有城市都被攻占,输出"Game Over."

三、代码实现

import sys
from collections import deque

def main():
    input = sys.stdin.read().split()
    ptr = 0
    N = int(input[ptr])
    ptr += 1
    M = int(input[ptr])
    ptr += 1

    adj = [[] for _ in range(N)]
    for _ in range(M):
        u = int(input[ptr])
        v = int(input[ptr + 1])
        ptr += 2
        adj[u].append(v)
        adj[v].append(u)

    K = int(input[ptr])
    ptr += 1
    lost_cities = list(map(int, input[ptr:ptr + K]))
    ptr += K

    def count_components(adj, N, removed=None):
        if removed is None:
            removed = set()
        visited = [False] * N
        components = 0
        for i in range(N):
            if i not in removed and not visited[i]:
                queue = deque([i])
                visited[i] = True
                while queue:
                    u = queue.popleft()
                    for v in adj[u]:
                        if v not in removed and not visited[v]:
                            visited[v] = True
                            queue.append(v)
                components += 1
        return components

    initial_components = count_components(adj, N)
    removed = set()

    for city in lost_cities:
        removed.add(city)
        new_components = count_components(adj, N, removed)
        if new_components > initial_components + 1:
            print(f"Red Alert: City {city} is lost!")
        elif new_components > initial_components:
            print(f"Red Alert: City {city} is lost!")
        else:
            print(f"City {city} is lost.")
        initial_components = new_components

    if len(removed) == N:
        print("Game Over.")

if __name__ == "__main__":
    main()

四、个人总结

在解决"红色警报"这一问题的过程中,我深刻体会到图论算法在实际问题中的应用价值。最初面对题目时,最困扰我的是如何准确判断城市被攻占对国家连通性的影响。通过分析,我意识到关键在于动态维护图的连通分量数量,这需要将图论知识与实际问题建立联系。在实现过程中,选择BFS而非DFS来计算连通分量,不仅避免了递归可能带来的栈溢出问题,也更符合直观的层级遍历思想。

调试阶段遇到的一个典型问题是初始连通分量的计算。最初我忽略了国家可能本来就不完全连通的情况,导致警报判断逻辑出现偏差。这个错误让我明白,在算法设计中必须全面考虑各种边界条件,特别是那些看似不常见但实际可能存在的场景。另外,在处理大规模输入时,如何高效管理被攻占城市集合也让我对数据结构的选择有了更深理解,使用集合而非列表来存储被攻占城市,使得查询操作的时间复杂度从O(n)降到了O(1)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值