PAT甲级1013 求图的连通分量
本题实际上是把检查点去掉后,求解图中连通分量的个数,结果用连通分量的个数减一。连通分量的求解使用并查集,把每一个连通分量的点,在自己所在的分量中找一个结点当做根,最后统计根的个数就行了。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
const int MAXM = 10000000;
int N, M, K, par[MAXN];
struct Arc {
int u, v;
} G[MAXM];
int Find(int x) { // 路径压缩的查找
int s;
for(s = x; par[s] >= 0; s = par[s]) {}
while(s != x) {
int t = par[x];
par[x] = s;
x = t;
}
return s;
}
void Union(int x, int y) {
int u = Find(x), v = Find(y);
int sum = par[u] + par[v];
if(par[u] < par[v]) {
par[u] = sum;
par[v] = u;
} else {
par[v] = sum;
par[u] = v;
}
}
void graph(int x) { // 检查点x的情况
memset(par, -1, sizeof(par));
for(int i = 0; i < M; ++i) {
int u = G[i].u, v = G[i].v;
if(u != x && v != x && Find(u) != Find(v)) { // 抛开特殊点
Union(u, v);
}
}
}
int main() {
cin >> N >> M >> K;
for(int i = 0; i < M; ++i) {
cin >> G[i].u >> G[i].v;
}
for(int i = 1; i <= K; ++i) {
memset(par, 0, sizeof(par));
int k, sum = 0;
cin >> k;
graph(k);
for(int i = 1; i <= N; ++i) {
if(par[i] < -1 || (par[i] == -1 && i != k)) { // 注意这里是<, -1的情况说明自己是单独的点
++sum;
}
}
cout << sum - 1 << endl;
}
return 0;
}