题目的意思是先给定一些边,然后删除某个点,计算使剩下的点联通所需的边数。
用并查集做,跳过删除点对应的边初始化father数组,然后计算根结点个数,有几个根节点就有几个独立的集合。使这些集合联通的最小边数为集合数-1。最后-3是因为,跳出for时的i对应的father[i]!=-1,即此时的i已经不是根结点,-1;连接n个不相连的集合需要n-1条边,再-1;根结点中还有一个点是删除的点,所以总共需要-3。
#include <stdio.h>
#include <algorithm>
const int maxn=1010;
using namespace std;
int father[maxn]={0};
bool g[maxn][maxn]={false};
int cityNum,roadNum,queryNum;
int findFather(int index){
int temp=index;
while(father[index]!=-1){
index=father[index];
}
while(father[temp]!=-1){
int t=father[temp];
father[temp]=index;
temp=t;
}
return index;
}
int query(int id){
fill(father+1,father+cityNum+1,-1);
for(int i=1;i<=cityNum;i++){
if(i==id)continue;
for(int j=i;j<=cityNum;j++){
if(j==id || !g[i][j])continue;
father[i]=j;
}
}
for(int i=1;i<=cityNum;i++){
findFather(i);
}
sort(father+1,father+cityNum+1);
int i;
for(i=1;father[i]==-1;i++){}
return i-3;
}
int main(){
scanf("%d %d %d",&cityNum,&roadNum,&queryNum);
for(int i=0;i<roadNum;i++){
int a,b;
scanf("%d %d",&a,&b);
g[a][b]=g[b][a]=true;
}
for(int i=0;i<queryNum;i++){
int queryid;
scanf("%d",&queryid);
printf("%d",query(queryid));
if(i<queryNum-1)printf("\n");
}
}