bzoj1015 [JSOI2008]星球大战starwar
Posted zbtrs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1015 [JSOI2008]星球大战starwar相关的知识,希望对你有一定的参考价值。
1015: [JSOI2008]星球大战starwar
Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 5134 Solved: 2328
[Submit][Status][Discuss]
Description
很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系。某一天,凭着一个偶然的
机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直
接或间接地连接。 但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划
地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。现在,反抗军首
领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每
一次打击之后反抗军占据的星球的连通快的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则
这两个星球在同一个连通块中)。
Input
输入文件第一行包含两个整数,N (1 < = N < = 2M) 和M (1 < = M < = 200,000),分别表示星球的
数目和以太隧道的数目。星球用 0 ~ N-1的整数编号。接下来的M行,每行包括两个整数X, Y,其中(0 < = X <>
Y 表示星球x和星球y之间有“以太”隧道,可以直接通讯。接下来的一行为一个整数k,表示将遭受攻击的星球的
数目。接下来的k行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这k个数互不相同,且都在0到n-1的范
围内。
Output
输出文件的第一行是开始时星球的连通块个数。接下来的N行,每行一个整数,表示经过该次打击后现存星球
的连通块个数。
Sample Input
0 1
1 6
6 5
5 0
0 6
1 2
2 3
3 4
4 5
7 1
7 2
7 6
3 6
5
1
6
3
5
7
Sample Output
1
1
2
3
3
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 400010; int n, m,fa[maxn],cur[maxn], head[maxn],flag[maxn],ans, k,tot, to[maxn], nextt[maxn],can[maxn]; void add(int a, int b) { tot++; to[tot] = b; nextt[tot] = head[a]; head[a] = tot; } int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } int main() { memset(flag, 1, sizeof(flag)); scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); add(x, y); add(y, x); } scanf("%d", &k); for (int i = 1; i <= k; i++) { scanf("%d", &can[i]); flag[can[i]] = 0; } for (int i = 0; i <= n; i++) fa[i] = i; ans = n - k; //先将每个点当作独立的点 for (int u = 1; u <= n; u++) //然后通过边的关系求出删掉要求删的点后的连通块的数量 if (flag[u]) { for (int i = head[u];i; i = nextt[i]) if (flag[to[i]]) { int x = find(u), y = find(to[i]); if (x != y) { fa[y] = x; ans--; } } } cur[k] = ans; int u; for (int t = k; t >= 1; t--) { flag[u = can[t]] = 1; //不断的添加点 ans++; for (int i = head[u]; i; i = nextt[i]) { if (flag[to[i]]) { int x = find(u), y = find(to[i]); if (x != y) { fa[y] = x; ans--; } } } cur[t - 1] = ans; } for (int i = 0; i <= k; i++) //最后顺着输出 printf("%d\n", cur[i]); return 0; }
以上是关于bzoj1015 [JSOI2008]星球大战starwar的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1015 [JSOI2008]星球大战starwar
bzoj 1015: [JSOI2008]星球大战starwar
BZOJ1015[JSOI2008]星球大战starwar[并查集]
BZOJ-1015: [JSOI2008]星球大战starwar (并查集)