时间:

2022.4.28

题解:

并查集 + 思维。正向难以求解,所以把题目反向理解为,一边添加点,一边求连通块个数。
此时初始状态就是其他所有已经存在的点组成的图。根据 fa[i] == i 统计联通块的个数。
然后按照输入的逆序添加点,刚添加的点独立,所以是一个新的连通块,cnt++。
然后枚举这个点相连的所有点,因为要连边。在它相连的点之间,如果存在一个点已经在图中出现,且它们两个不在一个连通块中,那么他们相连就会导致连通块数减一,即 cnt- -。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define endl "\n"
#define inf 0x3f3f3f3f
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define IOS ios::sync_with_stdio(0); cin.tie(0)
const int N = 100 + 4e5;

int tot, head[N], fa[N];

struct node
{
int to, next, val;
}e[N<<1];

void add(int u, int v)
{
e[tot].to = v; e[tot].next = head[u]; head[u] = tot++;
}

int get(int x)
{
if(fa[x] == x) return x;
return fa[x] = get(fa[x]);
}

void merge(int a, int b)
{
int dx = get(a);
int dy = get(b);
if(dx != dy)
{
fa[dx] = dy;
}
}

void slove()
{
memset(head, -1, sizeof head);

int n, m; cin>>n>>m;
for(int i = 0; i < n; i++) fa[i] = i;

vector<vector<int> > g(n);
vector<int> u(m), v(m);
for(int i = 0; i < m; i++)
{
cin>>u[i]>>v[i];
add(u[i], v[i]); add(v[i], u[i]);
}

int k; cin>>k;
vector<int> cut(k);
int mp[N];
for(int i = 0; i < n; i++) mp[i] = 0;
for(int i = 0; i < k; i++)
{
cin>>cut[i];
mp[cut[i]] = 1;
}

for(int i = 0; i < m; i++)
{
if(!mp[u[i]] && !mp[v[i]])
{
merge(u[i], v[i]);
}
}

int cnt = 0;
for(int i = 0; i < n; i++)
{
if(get(i) == i && !mp[i]) cnt++;
}

vector<int> ans(n);
for(int i = k-1; i >= 0; i--)
{
mp[cut[i]] = 0;
ans[i] = cnt;
cnt++;
for(int j = head[cut[i]]; ~j; j = e[j].next)
{
int v = e[j].to;
if(!mp[v] && get(cut[i]) != get(v))
{
cnt--;
merge(cut[i], v);
}
}
}
cout<<cnt<<endl;
for(int i = 0; i < k; i++) cout<<ans[i]<<endl;
}



int main()
{
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
IOS;
slove();
return 0;
}