今天买的晴神宝典终于到了,刚好找到这题有题解,代码写的是真的不错,简单易懂,就是写代码的风格跟我平常的风格不太一样,还是要适应一下,不过至少不用在网上找各种风格迥异的题解了,加油~~~~
# include <iostream>
# include <vector>
# include <cstring>
using namespace std;
/*
输入:
N(城市总数) M(路的数量) K(要检查是否到其他城市有通路的城市数量)
M条路(u->v)
K个待检查的城市的序号i
输出:
第i个城市如果沦陷了,那么剩下的城市为了形成通路应修的路的个数
创建邻接矩阵
使用DFS
*/
const int MAXSIZE = 1111;
vector<bool> visited(MAXSIZE);
vector<int> G[MAXSIZE];
// 在DFS中:对于遇到要删除的顶点,并不用真的删除,跳过即可
// 在主函数中:对于遇到要删除的顶点,不进行以其开始的连通分量的遍历(可以对其所在的连通分量换个起点,反正就不要已它为起点)
void DFS(int u, int occupied)
{
// 对于遇到要删除的顶点,并不用真的删除,跳过即可
if(u == occupied)
return;
visited[u] = true;
// for(size_t i=0;i<G[u].size();++i)
// {
// int v = G[u][i];
// if(visited[v] == false)
// DFS(v, occupied);
// }
for(size_t v=0;v<G[u].size();++v)
{
if(visited[G[u][v]] == false)
DFS(G[u][v], occupied);
}
}
int main()
{
int N, M, K;
cin >> N >> M >> K;
// 创建邻接表,要习惯晴神的写法……
for(int i=0;i<M;++i){
int a, b;
cin >> a >> b;
G[a].push_back(b); // a->b
G[b].push_back(a); // b->a
}
// 进行K次查询,每次都对图进行一次遍历
for(int i=0;i<K;++i){
int occupied; // 欲被删除(占领)的顶点
cin >> occupied;
visited = vector<bool>(MAXSIZE, false); // 对于每一次查询都要遍历一次图,所以visited数组要重新设置
int num_of_connected_component=0; // 用来记录连通分量的个数,
for(int u=1;u<=N;u++) // 枚举所有顶点
if(u != occupied && visited[u] == false){ // 跳过被删除和已被访问过的顶点
DFS(u, occupied); // 一条路走到底,说明每完成一次DFS函数,就有一个连通分量存在
num_of_connected_component++; // 所以连通分量的个数++
}
cout << num_of_connected_component - 1 << endl; // 想想,n个连通分量需要n-1条边来连接!!
}
return 0;
}