方案一
记录所有的边(可以用邻接表)
对每个丢失的城市(每个查询)
根据边,用并查集对城市进行集合的合并 O(e)
检查一共有n个集合,则需要修n-1条路 O(v)
代码如下:
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
const int maxn = 1010;
int findfather(int father[], int a) {
int x = a;
while (x != father[x]) {
x = father[x];
}
int temp;
while (father[a] != x) {
temp = father[a];
father[a] = x;
a = temp;
}
return x;
}
int main() {
int N, M, K;
int a, b; // two cities the highway connect
int c; // the lost city
vector<int> node[maxn];
scanf("%d %d %d", &N, &M, &K);
for (int m = 0; m < M; m++) {
scanf("%d %d", &a, &b);
node[a].push_back(b);
// node[b].push_back(a); // it is not neccisery if using union set
}
int father[maxn];
for (int k = 0; k < K; k++) {
scanf("%d", &c);
for (int i = 1; i <= N; i++) {
father[i] = i;
}
/*
// test
for (int i = 1; i <= 10; i++) {
printf("%d ", father[i]);
}
printf("\n");
*/
for (int i = 1; i <= N; i++) {
if (i == c) continue;
int fa = findfather(father, i);
for (int j = 0; j < node[i].size(); j++) {
if (node[i][j] == c) continue;
int fb = findfather(father, node[i][j]);
if (fa != fb) {
father[fb] = fa;
// // test
// for (int i = 1; i <= 10; i++) {
// printf("%d ", father[i]);
// }
// printf("\n");
}
}
}
set<int> countSet;
for (int i = 1; i <= N; i++) {
if (i == c) continue;
countSet.insert(findfather(father, i));
}
printf("%d\n", countSet.size() - 1);
}
return 0;
}
方案二
用邻接矩阵存储图(或者用邻接表)
对每个丢失的城市
根据图采用宽度(或深度)优先搜索,记录需要多少次搜索(即产生多少搜索树)
两个的复杂度应该都是O(v+e),其中v为顶点的数目,e为边的数目
代码如下:
其中,需要注意的是:visit 数组在DFS中表示“该结点是否被访问过”,而在BFS中表示“该结点是否进入过队列”,如果BFS中的定义与DFS中相同,则在PAT测试中,最后一个测试样例超时。原因是定义为“是否被访问过”将导致已经进入队列,但是没有被访问过的结点再次进入队列,从而产生重复,导致超时。
#include<cstdio>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int maxn = 1010;
void DFS(int i, vector<int> node[], bool visit[], int c) {
if (visit[i] == true) return;
else {
visit[i] = true;
if(node[i].size() == 0) return;
for (int j = 0; j < node[i].size(); j++) {
if (node[i][j] == c) continue;
DFS(node[i][j], node, visit, c);
}
}
return;
}
void BFS(int i, vector<int> node[], bool visit[], int c) {
queue<int> q;
q.push(i);
visit[i] = true;
while(!q.empty()) {
int temp = q.front();
q.pop();
for (int j = 0; j < node[temp].size(); j++) {
int temp2 = node[temp][j];
if (temp2 != c && visit[temp2] != true) {
q.push(temp2);
visit[temp2] = true;
}
}
}
}
int main() {
int N, M, K;
int a, b; // two cities the highway connect
int c; // the lost city
vector<int> node[maxn];
scanf("%d %d %d", &N, &M, &K);
for (int m = 0; m < M; m++) {
scanf("%d %d", &a, &b);
node[a].push_back(b);
node[b].push_back(a);
}
for (int k = 0; k < K; k++) {
scanf("%d", &c);
int countTimes = 0;
bool visit[maxn] = {false};
for (int i = 1; i <= N; i++) {
if (i == c) continue;
if (!visit[i]) {
countTimes++;
BFS(i, node, visit, c); // change the "BFS" to "DFS" will use the DFS method
}
}
printf("%d\n", countTimes - 1);
}
return 0;
}