一、题目
二、思路
把这些城市看做n个集合,每个集合中的任意两个元素都有直接或间接的路径相连,不同集合中的任意两个元素之间没有任何路径。这样每两个城市都连通就等价于任意两个集合都连通,共需要n-1条路,至于被占领的那个城市L,将其他城市与L之间的路(直接相连的)都断开,这样L单独构成一个集合,最后输出的时候减去这个集合就行了。
三、代码
#include<iostream>
#include <cstring>
using namespace std;
#define MAXSIZE 1001
int tag[MAXSIZE];//访问标记,已访问为1,未访问为0;
int G[MAXSIZE][MAXSIZE];//邻接矩阵,有路为1,无路为0
void dfs(int c,int N){//dfs之后,与c有直接或间接路径相连的城市会被标记为已访问
tag[c]=1;
for(int i=1;i<=N;i++){
if(tag[i]==0&&G[c][i]==1){
dfs(i,N);
}
}
}
int getRoads(int K,int N){
int memG[MAXSIZE];
//这里可以直接用tag[K]=1代替修改G,
//但是我提交的时候最后一个测点总是运行超时,所以就修改G
for (int i = 1; i <= N; ++i) {
memG[i]=G[K][i];
G[K][i]=G[i][K]=0;
}
//tag[K]=1;
int num=0;
for (int j = 1; j <= N; ++j) {
//对于未访问过滴城市,访问它和与它相连滴城市
if(tag[j]==0){
dfs(j,N);
num++;
}
}
//恢复
for (int i = 1; i <= N; ++i) {
G[K][i]=G[i][K]=memG[i];
}
memset(tag,0, sizeof(tag));
return num;
}
int main()
{
int N,M,K;
cin>>N>>M>>K;
int cityLost[K];
int roadNum[K];
memset(G,0, sizeof(G));
for (int i = 0; i < M; ++i) {
int c1,c2;
cin>>c1>>c2;
G[c1][c2]=G[c2][c1]=1;
}
for (int i = 0; i < K; ++i){
cin>>cityLost[i];
roadNum[i]=getRoads(cityLost[i],N);
}
for (int i = 0; i < K; ++i) {
cout<<roadNum[i]-2<<endl;//n个集合需要n-1条路,这n个集合里包含了被占领的那个城市,所以还要再-1
}
return 0;
}