PAT A1013 Battle Over Cities (25分)
图的实现方式主要有两种:1.邻接表 2.邻接矩阵
邻接矩阵在顶点数目大于1000的情况就基本不适用了,而邻接表的链表实现在考试中代码量偏大
所以采取变成数组构建邻接表可以简化程序书写
邻接表的表示为:vector
当然本题还可以利用并查集的数据结构完成快速合并与查询,见代码2,但其实不建议使用并查集,因为并查集虽然容易确定是否连通但是最大的缺点就是很难删除,为了完成删除k次的操作
只能在每次查询阶段建立并查集,没有DFS和BFS来的简便和明显
注意:
- 使用并查集必须进行路径压缩否则会导致数据超时
- 由于是无向图,在读入数据两个方向的边都需要存储
代码1:邻接表+DFS
#include <cstdio>
#include <vector>
#include <string.h>
using namespace std;
const int N = 1010;
vector<int> G[N];//从1开始
bool vis[N];//从1开始
void DFS(int a,int check){
if(a==check||vis[a]==true) return;
else{
vis[a] = true;
for(int i = 0;i<G[a].size();i++){
DFS(G[a][i],check);
}
return;
}
}
int main(){
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i = 0;i< m;i++){
int a,b;
scanf("%d%d",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
}
int check;
for(int i = 0 ; i < k;i++){//k次查询
scanf("%d",&check);
memset(vis,false,sizeof(vis));
int block = 0;//连通块个数
for(int j = 1; j <= n;j++){
if(j!=check&&vis[j]==false){
DFS(j,check);
block++;
}
}
printf("%d",block-1);
if(i < k-1) printf("\n");
}
return 0;
}
代码2:邻接表+并查集
#include <cstdio>
#include <vector>
#include <string.h>
using namespace std;
const int N = 1010;
vector<int> G[N];//从1开始
bool vis[N];//从1开始
int father[N];//从1开始
void init(int n){//从1到n
for(int i = 1;i<=n;i++){
father[i] = i;
vis[i] = false;
}
return;
}
int findFather(int x){
int a = x;
while(x!=father[x]){
x = father[x];
}
//路径压缩
while(a!=father[a]){
int z = a;
a = father[a];
father[z] = x;
}
return x;
}
void Union(int a,int b){
int fa = findFather(a);
int fb = findFather(b);
if(fa!=fb) father[fa] = fb;
return;
}
int main(){
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i = 0;i< m;i++){
int a,b;
scanf("%d%d",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
}
int check;
for(int i = 0 ; i < k;i++){//k次查询
scanf("%d",&check);
init(n);
//建立当前并查集
for(int j = 1; j <= n;j++){
if(j!=check){
for(int d = 0;d<G[j].size();d++){
if(G[j][d]!=check){
int v = G[j][d];
int u = j;
Union(v,u);
}
}
}
}
int block = 0;//连通块个数
for(int j = 1;j <= n;j++){//遍历n个结点
if(j != check){
int fa = findFather(j);
if(vis[fa]==false){
block++;
vis[fa] = true;
}
}
}
printf("%d",block-1);
if(i < k-1) printf("\n");
}
return 0;
}