题目链接
题目分析
1、无向图
2、节点编号1-N
3、删去一个结点,查看变成几个连通块
解题思路
- 思路(一)
DFS
遍历看剩余接个连通块(即DFS
的次数)
对于删除结点,只需把结点设置为已访问即可(vis[key] = true;
) - 思路(二)
用并查集算法查看共有多少集合;
由于要多次删除一个结点进行查询,只能把图信息先完整保存下来,之后每次查询都重新合并集合即可!
思路(一)(DFS遍历)
/**********************************
*@Author: 3stone
*@ACM: PAT.A1013 Battle Over Cities
*@Time: 18/8/12
*@IDE: VSCode 2018 + clang++
***********************************/
#include<cstdio>
using namespace std;
const int maxn = 1010;
int N, M, K; //结点数,边数,查询数
int G[maxn][maxn]; //邻接矩阵
bool vis[maxn] = {false}; //标记结点是够访问
void DFS(int u) {
vis[u] = true;
for(int i = 1; i <= N; i++)
if(vis[i] == false && G[u][i] != 0)
DFS(i);
}
int main() {
int node_a, node_b;
while(scanf("%d%d%d", &N, &M, &K) != EOF) {
//初始化 所有结点无连接
for(int i = 0; i < maxn; i++)
for(int j = 0; j < maxn; j++)
G[i][j] = 0; //本题为无权图
//输入图信息
for(int i = 1; i <= M; i++) { //输入边的信息
scanf("%d%d", &node_a, &node_b);
G[node_a][node_b] = 1; //无向图
G[node_b][node_a] = 1;
}
int lost; //保存丢失的结点编号
int num; //记录连通块数(DFS次数)
//逐个检查(删去)
for(int i = 1; i <= K; i++){
for(int i = 0; i < maxn; i++ ){
vis[i] = false;
}
num = 0;
scanf("%d", &lost);
vis[lost] = true; //标记为已访问,相当于丢失
for(int j = 1; j <= N; j++){
if(vis[j] == false){
DFS(j);
num++;
}
}
printf("%d\n", num - 1); //输出需要添加的边数
}
}//while
return 0;
}
思路(二)并查集:
/**********************************
*@Author: 3stone
*@ACM: PAT.A1013 Battle Over Cities
*@Time: 18/8/12
*@IDE: VSCode 2018 + clang++
***********************************/
#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 1010;
int M, N, K;
vector<int> G[maxn]; //图-邻接表存储
int farther[maxn];
//并查集初始化
void init() {
for(int i = 0; i < maxn; i++)
farther[i] = i;
}
//寻根
int find_root(int a) {
int root = a;
while(root != farther[root])
root = farther[root];
//路径压缩
while(a != farther[a]) {
int cur = a;
a = farther[a];
farther[cur] = root;
}
return root;
}
//合并集合
void union_set(int a, int b) {
int root_a = find_root(a);
int root_b = find_root(b);
if(root_a != root_b) { //对集合B进行路径压缩
while(b != farther[b]){
int cur = b;
b = farther[b];
farther[cur] = root_a;
}
farther[root_b] = root_a;
}
}
int main() {
int a, b, tar, num_of_set;
while(scanf("%d%d%d", &N, &M, &K) != EOF) {
for(int i = 0; i <= N; i++) G[i].clear();
//保存图
for(int i = 0; i < M; i++) {
scanf("%d%d", &a, &b);
G[a].push_back(b);
G[b].push_back(a);
}
for(int i = 0; i < K; i++) {
scanf("%d", &tar);
init();
num_of_set = 0;
//合并集合
for(int u = 1; u <= N; u++){
if(u == tar) continue;
for(int v = 0; v < G[u].size(); v++){
if(G[u][v] == tar) continue;
union_set(u, G[u][v]);
}
}
//查询更结点数
for(int j = 1; j <= N; j++)
if(j != tar && j == farther[j]){
num_of_set++;
}
printf("%d\n", num_of_set - 1);
}
}
return 0;
}