L2-013 红色警报
解题思路
要对连通块的数量计数,很明显要建图,但是建图用什么呢?
-
邻接矩阵,常常用一个二维数组,例如e[510][510]来表示二者之间是否有相连关系,优点是容易获取指定的二者的关系,缺点是无法应对大数据量。
适用于稠密图,点少边多。 -
邻接表,可以用原始数组模拟,也可以使用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;
}

浙公网安备 33010602011771号