题目链接:PAT【甲级】1013
题目简述:输入N,M,K
三个正整数(N
为城市数量,M
为城市间道路数量,K
为要查询的案例数),然后输入M
组格式为c1 c2
的数字,分别代表两个城市之间连有通路。下面则数输入K
个数,表示删除这个节点后,还需要建立多少条路来使得各城市节点互通。
#include<bits/stdc++.h>
using namespace std;
vector<vector<int>> graph(1000, vector<int>(1000, 0));
vector<int> visit(1000, 0);
void dfs(int beg, int N){
for (int i = 1; i <= N;i++){
if(visit[i] == 0 && graph[i][beg] == 1){
visit[i] = visit[beg];
dfs(i, N);
}
}
}
int getBlockNum(int N){
int num = 0;
for (int i = 1; i <= N;i++){
if(visit[i] == 0){
num++;//连通块数加1
visit[i] = num;
dfs(i, N);
}
}
return num;
}
int main(){
int N, M, K;
int c1, c2, u;
cin >> N >> M >> K;
for (int i = 0; i < M;i++){
cin >> c1 >> c2;
graph[c1][c2] = graph[c2][c1] = 1;
}
for (int i = 0; i < K;i++){
cin >> u;
visit[u] = -1;//将u节点设置为遗弃节点
cout << getBlockNum(N) - 1 << endl;
for (int j = 0; j < 1000;j++)//重置visit数组
visit[j] = 0;
}
return 0;
}
这个题目读完之后,其实就知道是应该用连通块这个点来求解。开始状态是一个连通块,删除一个节点后变成n
个连通块,那么要建立的最少通路数便是n-1
。
开始我本想着通过一种方法来一劳永逸,即预处理后,下面每输入一个数字便立刻就能得到答案,后来发现似乎不太可能实现,所以就K
次连通块求解了。
这个题解在我写完通过之后,又看了其他人的题解,发现不同的地方是:
- 其他人对
visit
数组设置的是bool
类型,可以看到我设置的是int
类型,这样做的目的在这道题当中都是一样的:避免重复查找。但我的设计显得多余,浪费内存。 - 还有一点,便是遗弃节点的考虑,我开始设计的是传入参数,在
if
中判断i != dispute
,后来看到别人的设计是将visit[dispute] = true;
来表示已访问,来跳过查询。我受此启发,将visit[dispute] = -1;
来达到此目的。