1、知识点:连通分量
2、思路:题意为:去掉一个点以及与它相连的边,问剩余点的连通分量数是多少。可用并查集求解。
/*用途:
**说明:
**算法:并查集
*/
//#define LOCAL
#include <cstdio>
#include <string.h>
using namespace std;
#define MAXN 1000+10
#define MAXM 500000+10
#define MAXK MAXN
int N, M, K;
int pre[MAXN];
int block[MAXN];
int conn[MAXM][2];
inline void init_pre(); //初始化每个点的顶级结点
int find(int x);
void uni(int x, int y);
int main()
{
#ifdef LOCAL
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
#endif
scanf("%d%d%d", &N, &M, &K);
for(int i=0; i<N; i++)
pre[i] = i;
for(int i=0; i<M; i++)
scanf("%d%d", &(conn[i][0]), &(conn[i][1]));
for(int i=0; i<K; i++){
int city;
scanf("%d", &city);
init_pre();
for(int j=0; j<M; j++)
if(city!=conn[j][0] && city!=conn[j][1]) //如果该点与这条边不相关,就将该边的两个端点做uni操作
uni(conn[j][0], conn[j][1]);
memset(block, 0, sizeof(block));
for(int j=0; j<N; j++)
block[find(j)] = 1;
int ans = 0;
for(int j=0; j<N; j++)
if(block[j])
ans++;
printf("%d\n", ans-2);
}
return 0;
}
inline int find(int x)
{
int top = x;
while(top != pre[top])
top = pre[top];
int temp; //暂时保存x以前的上级结点
while(pre[x] != top){ //路径压缩,如果不做会超时
temp = pre[x];
pre[x] = top;
x = temp;
}
return top;
}
inline void uni(int x, int y)
{
int fx, fy;
fx = find(x);
fy = find(y);
if(fx != fy)
pre[fx] = fy;
}
inline void init_pre()
{
for(int i=0; i<N; i++)
pre[i] = i;
}