题目
解题思路
本题的考察的点就是连通分量的个数问题,想要解决这个问题,得知道一个知识:
- 如果当前有5个城市,且每个城市之间不互通,即5个独立的连通分量,那么需要4条边就可以将其连通。
本题就是考察,当一个城市消失后,其所在的边也会跟着消失,那么需要修几条路可以让其他城市连通起来,比如:
- 当前有5个顶点,有5条边,分别为1—2,2—3,3—4,3—5,1—3。那么现在失去3号顶点,那么其所在的边也要失删除,那么需要添加几条边使得剩下的顶点可以连通。发现,删除3号顶点后,只剩下3个连通分量,分别为,1—2,4,5。那么需要修两条边就可以使其连通。
这就是本题的一个思路,通过用dfs求连通图数量得出需要修建的公路数。
说一下,这个题最后一行如果有换行符也是可以通过的,
实现代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<sstream>
#include<algorithm>
using namespace std;
constexpr auto MAXN = 1001;
int G[MAXN][MAXN];
bool vis[MAXN]; //标记数组,用来标记是否访问过该顶点
int N,num,M;
int temp,cnt=0;
//DFS深度优先遍历
void DFS(int v)
{
vis[v]=true;
for(int i=1;i<=N;i++)
{
//当前节点是否被访问过以及从顶点v出发,是否有到顶点i的边
//一定要给是未访问过的节点,如果访问过的节点,你再访问,连通分量的个数就会算重复
if(vis[i]==false && G[v][i]==1)
DFS(i);
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif
cin>>N>>num>>M;
int a,b;
for(int i=0;i<num;++i)
{
cin >> a >>b;
G[a][b]=G[b][a]=1; //无向图
}
//这个循环表示对题目给定的M个数进行处理
for(int i=0;i<M;++i)
{
cin >> temp;
//cnt一定要在这里给一个初始化,注意一下,我设置的是全局变量
//因为每次接受一个被军队占领的城市,也就是该顶点要删除,我们要计算删除该顶点后,需要修建的公路
//然后接受下一个的时候是要复原的,也就是按初始图的样子进行操作,所以cnt置零
cnt=0;
//这个和cnt一个道理,要复原,那么vis标记数组就得刷新。temp的每个取值是独立的,不是相关的(题目要求)
fill(vis,vis+MAXN,false);
//这一步我解释一下,正常我们dfs遍历图,或者求连通分量个数,是在for和if中间加这句代码的
//那这里把这句代码放这个位置其实就是模拟该顶点被删除的意思,即该城市被占领
//因为把该顶点置为true,就意味着该顶点不会调用dfs,就是说该顶点不会被作为起点,那么自然也就不会去遍历从该顶点出发的所有边,所以这一步很重要
vis[temp]=true;
//这个for循环表示当前删除的顶点下,从其他顶点出发分别对其进行dfs
for(int j=1;j<=N;++j)
{
if(vis[j]==false)
{
//这里就基本操作,从顶点j出发,遍历其可以到达且未被访问过的顶点,然后每调用一次dfs函数,cnt++,表示从该顶点出发是有一个连通分量的
DFS(j);
cnt++; //一定是放在这里++,而不是放到if外面
}
}
cout<<cnt-1<<endl;
}
return 0;
}
Comments | 1 comment
Blogger Lenny Hofler
Awesome post! Your style is captivating and your opinions are very relevant. Thanks for sharing such useful information with us. Keep it up!