题解:
同样是一道好题,考查了我们对于逆向思维的理解。从最后开始加点,每次询问剩下联通块的个数,这样就迎刃而解了。
/*
ID:Agreement
LANG:C++
*/
// Invincible
#include <bits/stdc++.h>
#define rep( i , l , r ) for( int i = (l) ; i <= (r) ; ++i )
#define per( i , r , l ) for( int i = (r) ; i >= (l) ; --i )
#define erep( i , u ) for( int i = head[(u)] ; ~i ; i = e[i].nxt )
using namespace std;
inline int _read(){
register int x = 0 , f = 1;
register char ch = getchar();
while( ch > '9' || ch < '0' ) { if( ch == '-' ) f = -1; ch = getchar(); }
while( ch >= '0' && ch <= '9' ){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
const int maxn = 400000 + 5;
int N , M , d , tot , f[maxn] , head[maxn] , q[maxn] , ans[maxn] , _t = 0;
bool used[maxn] , des[maxn];
struct edge{
int v , nxt;
}e[maxn];
inline void ins( int u , int v ){
e[_t].v = v , e[_t].nxt = head[u] , head[u] = _t; _t++;
e[_t].v = u , e[_t].nxt = head[v] , head[v] = _t; _t++;
}
int getfa( int x ){ return x == f[x] ? x : f[x] = getfa(f[x]); }
inline void add( int x ){
int p = getfa(x) , q , v;
erep( i , x )
if( used[e[i].v] ){
q = getfa( e[i].v );
if( p != q ) f[q] = p , tot--;
}
}
int main(){
memset( head , 0xff , sizeof head );
int u , v;
N = _read() , M = _read();
rep( i , 0 , N - 1 ) f[i] = i;
rep( i , 1 , M ){
u = _read() , v = _read();
ins( u , v );
}
d = _read();
rep( i , 1 , d ) q[i] = _read() , des[q[i]] = 1;
rep( i , 0 , N - 1 )
if( !des[i] ){
++tot , add( i ) , used[i] = 1;
}
ans[d + 1] = tot;
per( i , d , 1 ){
tot++ , add( q[i] ) , used[q[i]] = 1 , ans[i] = tot;
}
rep( i , 1 , d + 1 ) printf("%d\n" , ans[i]);
return 0;
}