L2-013 红色警报

L2-013红色警报

解题思路

要对连通块的数量计数,很明显要建图,但是建图用什么呢?

  1. 邻接矩阵,常常用一个二维数组,例如e[510][510]来表示二者之间是否有相连关系,优点是容易获取指定的二者的关系,缺点是无法应对大数据量。
    适用于稠密图,点少边多。

  2. 邻接表,可以用原始数组模拟,也可以使用vector数组模拟(后者方便太多,在天梯赛更常见),优点是可以应对大数据量,缺点是必须遍历一遍才知道关系。
    适用于稀疏图,点多边少。

本题柳婼大大使用的是邻接矩阵,但是这道题更适合使用邻接表,更容易写dfs函数,在天梯赛出现的频率也更高

这里演示邻接表

同时,本题的关键判断就是连通块的数量是否发生改变,当一座重要城市沦陷之后,连通块数量改变,那么我们只需要判断前后连通块数量是否相等就行了

并非如此

  • 如果它是作为要塞沦陷的,连通块的数量会增加,这时候要报警;

  • 如果它是独立的城市沦陷,连通块数量会减少,但是我们不需要报警;

  • 如果它不是独立城市,但并不是要塞,我们也不需要报警;

所以并不是单纯地判断连通块数量想不相等,而是有明确的大小关系。同时我们也很容易发现,作为要塞的条件是它的邻接表中存放着其他邻接表中不存在的城市。这题由于数据小,用邻接矩阵也可以,而且邻接矩阵是把所有点遍历一遍,有些许暴力思想在,不过这道题如果用邻接表更能起到练习巩固作用。

O(∩_∩)O

对于递归不熟悉的可以看一下有关树的遍历(不是天梯赛题)相关的知识

ac✅️代码

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;

vector<int> a[10010];
bool lost[10010];
bool vis[10010];

int n,m;
//统计连通块的数量,显然沦陷的城市不能算在连通块里

void dfs(int u)
{
	vis[u] = true;
	for(auto v : a[u])
	{
		if(!lost[v] && !vis[v])
		{
			dfs(v);
		}
	}
}

int cnt()
{
	int res = 0;
	
	memset(vis,false,sizeof vis);
	
	for(int i = 0 ; i < n ; i ++)
	{
		if(!lost[i] && !vis[i])
		{
			res ++;
			dfs(i);
		}
	}
	return res;
}

int main()
{
	cin>>n>>m;
	while(m--)
	{
		int l,r;cin>>l>>r;
		
		a[l].push_back(r);
		a[r].push_back(l);
		
	}
	
	int k;cin>>k;
	int cnt1 = cnt();
	while(k--)
	{
		int lost_city;
		cin>>lost_city;
		lost[lost_city] = true;
		
		int cnt2 = cnt();
		
		if(cnt1 < cnt2) printf("Red Alert: City %d is lost!\n", lost_city);
		else printf("City %d is lost.\n", lost_city);
		
		if(k == 0) cout<<"game over\n";
		cnt1 = cnt2;
	}
	return 0;
}

posted @ 2026-03-15 15:17  shuiwangrenjia  阅读(10)  评论(0)    收藏  举报