一、答案
题目的意思其实可以翻译为:给点一些点和边,去掉某一点及与其相连的边后,该图的连通分支为多少。
#include <iostream>
using namespace std;
int city_root[1000];
int find_root(int i); //寻找根节点函数
void city_root_intialization(int* city_root,int city_num); //各城市结点根节点初始化函数
void connect_city(int i,int j); //城市连接函数(合并函数)
int main()
{
int city_num=0,highway_num=0,check_num=0;
city_root_intialization(city_root,city_num); //各城市结点根节点初始化
cin>>city_num>>highway_num;
cin>>check_num;
int** highway;
highway=new int*[highway_num];
for(int i=0;i<highway_num;i++){ //写入道路数据
highway[i]=new int[2];
cin>>highway[i][0]>>highway[i][1];
}
for(int i=0;i<check_num;i++){ //依次遍历需关注的城市
int occ_city=0;
cin>>occ_city;
city_root_intialization(city_root,city_num);
for(int i=0;i<highway_num;i++){ //根据公路数据,对各城市进行连接合并,每一群城市由一个城市(根节点城市)代表
if(highway[i][0]!=occ_city&&highway[i][1]!=occ_city){
connect_city(highway[i][0],highway[i][1]);
}
}
int* check_group; //判断代表城市数量,得知由城市与公路构成的连通分支数,而需重建的公路为连通分支数-2(被破坏的城市不需要重建公路)
check_group=new int[city_num];
city_root_intialization(check_group,city_num);
for(int k=0;k<city_num;k++){
check_group[find_root(k)]=0;
}
int group_num=0;
for(int k=0;k<city_num;k++){
if(check_group[k]==0){
group_num++;
}
}
cout<<group_num-2<<endl;
}
return 0;
}
int find_root(int i) //寻找父节点函数:不断递归寻找父节点,直至没有父节点
{
if(city_root[i]==i){
return i;
}else{
city_root[i]=find_root(city_root[i]); //路径压缩
return city_root[i];
}
}
void connect_city(int i,int j) //连接两个城市:将两城市的根节点统一
{
if(find_root(i)!=find_root(j)){
city_root[find_root(i)]=find_root(j);
}
return;
}
void city_root_intialization(int* city_root,int city_num) //各城市结点根节点初始化函数
{
for(int i=0;i<city_num;i++){
city_root[i]=i;
}
return;
}
二、坑点
要使用并查集和路径压缩,否则最后的测试点没法通过
三、相关知识
并查集和路径压缩的相关知识可见以下链接:
最后,萌新写文,如有不足,还望指正