PAT A1013 Battle Over Cities
Sample Input:
3 2 3
1 2
1 3
1 2 3
Sample Output:
1
0
0
-
分析:
题意即:找去掉某一结点及其所有边后,剩下的图的连通块数 -
思路 1:
- 每次查询先重置标记数组flag[],将要查询结点"注释掉",标记为true,这样其他节点就到不了它(相当于删除这个节点及其所有边)
- 每DFS一次,cnt++(cnt及剩余图的连通块数)
- 输出cnt-1,把这些连通块连在一起至少需要的边数
- code 1:
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
int city, remain, check, cnt;
int G[maxn][maxn];
bool flag[maxn];
void DFS(int idex){
flag[idex] = true;
for(int i = 1; i <= city; ++i){
if(flag[i] == false && G[idex][i] == 1){
DFS(i);
}
}
}
void DFSTravel(){
for(int i = 1; i <= city; ++i){
if(flag[i] == false){
DFS(i);
cnt++;
}
}
}
int main(){
scanf("%d %d %d", &city, &remain, &check);
int c1, c2, que;
fill(G[0], G[0]+maxn*maxn, 0);
for(int i = 0; i < remain; ++i){
scanf("%d %d", &c1, &c2);
G[c2][c1] = G[c1][c2] = 1;
}
for(int i = 0; i < check; ++i){
fill(flag, flag+maxn, false);
cnt = 0;
scanf("%d", &que);
flag[que] = true;
DFSTravel();
printf("%d\n", cnt-1);
}
return 0;
}
- T2 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int G[maxn][maxn];
bool vis[maxn];
void DFS(int id, int n){
vis[id] = true;
for(int i = 1; i <= n; ++i){
if(vis[i] == false && G[id][i] == 1){
DFS(i, n);
}
}
}
int DFSTraversal(int n){
int cnt = 0;
for(int i = 1; i <= n; ++i){
if(vis[i] == false){
DFS(i, n);
cnt++;
}
}
return cnt > 0 ? cnt-1 : 0;
}
int main(){
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for(int i = 0; i < m; ++i){
int c1, c2;
scanf("%d %d", &c1, &c2);
G[c1][c2] = 1;
G[c2][c1] = 1;
}
for(int i = 0; i < k; ++i){
int que;
scanf("%d", &que);
vis[que] = true;
printf("%d\n", DFSTraversal(n));
memset(vis, false, sizeof(vis));
}
return 0;
}
-
思路 2:并查集
将除“删除结点” 以外的,在同一连通块内的结点加入同一集合,再遍历一个有几个集合 -
code 2:
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
int city, remain, check, cnt;
int G[maxn][maxn], father[maxn];
bool flag[maxn];
void init(){
for(int i = 0; i < maxn; ++i) father[i] = i;
}
int findRoot(int x){
int a = x;
while(x != father[x]){
x = father[x];
}
// int a; //...段错误,a为初始化!!
while(a != father[a]){
int t = a;
a = father[a];
father[t] = x;
}
return x;
}
void Union(int x, int y){
int rx = findRoot(x);
int ry = findRoot(y);
if(rx != ry) father[rx] = ry;
}
int main(){
scanf("%d %d %d", &city, &remain, &check);
int c1, c2, que;
fill(G[0], G[0]+maxn*maxn, 0);
for(int i = 0; i < remain; ++i){
scanf("%d %d", &c1, &c2);
G[c2][c1] = G[c1][c2] = 1;
}
for(int i = 0; i < check; ++i){
scanf("%d", &que);
init();
int cnt = 0;
fill(flag, flag+maxn, false);
for(int j = 1; j <= city; ++j)
for(int k = 1; k <= city; ++k)
if(G[j][k] == 1 && j != que && k != que)
Union(j, k);
for(int i = 1; i <= city; ++i){
int f = findRoot(i);
if(flag[f] == false && i != que){
cnt++;
flag[f] = true;
}
}
printf("%d\n", cnt-1);
}
return 0;
}
- T2 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int father[maxn], G[maxn][maxn];
bool has[maxn];
void Init(int n){
for(int i = 1; i <= n; ++i) father[i] = i;
}
int FindFather(int x){
int tmp = x;
while(father[x] != x){
x = father[x];
}
while(father[tmp] != tmp){
int tmp2 = tmp;
tmp = father[tmp];
father[tmp2] = x;
}
return x;
}
int Union(int a, int b){
int fa = FindFather(a);
int fb = FindFather(b);
if(fa != fb){
father[fb] = fa;
}
}
int Cnt(int n, int q){
for(int i = 1; i <= n; ++i){
for(int j = i + 1; j <= n; ++j){
if(i != q && j != q && G[i][j] == 1){
Union(i, j);
}
}
}
int cnt = 0;
memset(has, false, sizeof(has));
for(int i = 1; i <= n; ++i){
if(i != q){
int r = FindFather(i);
if(has[r] == false){
cnt++;
has[r] = true;
}
}
}
return cnt - 1;
}
int main(){
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for(int i = 0; i < m; ++i){
int c1, c2;
scanf("%d %d", &c1, &c2);
G[c1][c2] = 1;
G[c2][c1] = 1;
}
for(int i = 0; i < k; ++i){
int que;
Init(n);
scanf("%d", &que);
printf("%d\n", Cnt(n, que));
}
return 0;
}