HansLimon @ 2020-03-17 12:14:23
已经做了一天了qwq,
思路就是先离线,然后反过来从最后炸完了回到最初还没被炸的时候。
\kkkkkkkk \kel
然后这里是代码:
#include <cstdio>
const int N = 4e5 + 7, M = 2e5 + 7;
int n, m, k, cnt, ans, first[N], fa[N], time[M], otp[M];//cnt、first是前向星的,time表示第几次炸的是哪一个,ans是统计当前的连通块,otp是输出的答案(也就是记录了所有的ans)
bool damaged[N];//表示是否被炸
struct edges{
int v, next;
}edge[M<<1];
inline void add_edge(int u, int v){
edge[++ cnt] = (edges){v, first[u]};
first[u] = cnt ++;
edge[cnt] = (edges){u, first[v]};
first[v] = cnt;
}
inline int find(int x){return fa[x] == x?x:fa[x] = find(fa[x]);}
inline bool check(int x, int y){return find(x) == find(y);}
inline bool merge(int x, int y){
if (check(x, y))return false;
return fa[fa[x]] = fa[y], true;
}
int main(){
scanf("%d %d", &n, &m);
for (register int i = 0;i < n;i ++)fa[i] = i;
for (register int i = 1, x, y;i <= m;add_edge(x, y), i ++)scanf("%d %d", &x, &y);
scanf("%d", &k);
ans = n - k;
for (register int i = 1;i <= k;damaged[time[i]] = true, i ++)scanf("%d", time + i);
for (register int i = 0;i < n;i ++)
if (damaged[i])continue;
else for (register int j = first[i];j;j = edge[j].next)if (!damaged[edge[j].v] && merge(i, edge[j].v))ans --;
otp[k + 1] = ans;
for (register int i = k;i;otp[i] = ++ ans, i --)for (register int j = first[time[i]];j;j = edge[j].next)if (!damaged[edge[j].v] && merge(time[i], edge[j].v))ans --;
for (register int i = 1;i <= k + 1;i ++)printf("%d\n", otp[i]);
return 0;
}
by Bla_Bla @ 2020-03-17 12:15:42
qndmx!qnd刚学OI
by iMya_nlgau @ 2020-03-17 12:16:29
刚学OI 0秒
已经做了一天了
我谔谔
by 血色黄昏 @ 2020-03-17 12:17:19
刚学OI就爆切蓝题...
窝AFO了
by disangan233 @ 2020-03-17 12:22:56
刚学OI就爆切蓝题...
窝AFO了
by 地铁dixiatielu @ 2020-03-17 12:25:20
刚学OI就爆切蓝题...
窝AFO了qwq
by ⚡小林子⚡ @ 2020-03-17 12:28:22
@HansLimon 标题党
by Scherzo @ 2020-03-17 12:28:47
刚学OI就爆切蓝题...
窝AFO了qwq
by ⚡小林子⚡ @ 2020-03-17 12:29:08
话说标题党应该@谁
by lndjy @ 2020-03-17 12:37:03
刚学OI就爆切蓝题...
窝AFO了qwq
by Alan_Zhao @ 2020-03-17 12:40:37
这种标题党就应该 @管理员