题目描述
英文
中文大意
给定一个城市图,指出多少条高速公路需要被修复
举例:有3个城市 c1, c2, c3
2条公路连接 c1, c2
和 c1, c3
如果把c1
从图中移去,我们就需要修复 1
条公路来连接 c2, c3
输入
第一行包含 3个数字:N(<1000), M, K
N
:城市数量
M
:剩余公路数量
K
:被检查城市数量
接下来的 M
行用两个整数描述 高速公路
最后一行包含 K
个数字,展示了我们在意的城市节点
输出
对于 K
个城市而言,如果这个城市节点丢失了,在一行内输出我们书要修复多少条公路
样例
思路分析
把题目抽象化,其实就是一个图,然后把图中的某一点,抽掉
问:剩余的图需要添加多少条边,才能变成连通的?
使用DFS
深度优先遍历,计算剩余节点有几个独立区域,然后再添加边 把这几个独立区域连接起来
原理:如果图是连通的,那么DFS
一定可以把图全部搜索完毕
否则,需要 构建公路(也就是边edge
) ,且边的数量为 独立区域数量 减一
code
#include <iostream>
#include <string>
#define NumOfNode 1001
using namespace std;
int edge[NumOfNode][NumOfNode];
bool visited[NumOfNode];
// the total number of cities the number of remaining highways the number of cities to be cheaked
int N, M, K;
void dfs(int node) {
visited[node] = true;
for (int i = 1;i <= N;i++) {
// 未访问过 且 存在边
if (!visited[i] && edge[node][i] == 1)
dfs(i);
}
}
int main () {
scanf("%d%d%d", &N, &M, &K);
// 初始化边
for (int i = 0;i < M;i++) {
int c1, c2;
scanf("%d%d", &c1, &c2);
edge[c1][c2] = edge[c2][c1] = 1;
}
int city;
int res;
for (int i = 0;i < K;i++) {
// 对于每个节点而言 所以每次重置 res
res = 0;
// 同时重置 visited 数组
fill(visited, visited + NumOfNode-1, false);
scanf("%d", &city);
visited[city] = true;
// 此处的原理是 如果该区域连通 则通过dfs必能完全搜索,否则的话dfs只能搜索完该区域
// n 个独立区域 都需要 n - 1 条公路来把他们连通
for (int j = 1;j <= N;j++) {
if (!visited[j]) {
dfs(j);
// 独立区域+1
res++;
}
}
printf("%d\n", res-1);
}
return 0;
}