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

第一行是开始时星球的连通块个数。接下来的K行,每行一个整数,表示经过该次打击后现存星球
的连通块个数


Sample Input

8 13
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
1
2
3
3


题解:

  显然一看就知道是并查集,但是需要不断删除点,然而并查集并不支持删除操作。而且路径压缩过后,每个点显然只与根节点有关系而找不到子节点与其他子节点的关系了,所以只能反过来做,先求出所有星球被炸完后的连通分量,再把被炸的星球一个一个加上去,维护连通分量个数即可。

  另外最后输出答案的时候用cout就runtime error??害得我查了一小时的bug...我真他娘服了

 #include <iostream>
#include <string.h>
#include <cstdio>
#include <algorithm>
#include <queue>
#pragma warning ( disable : 4996 ) #define sigma_size 26 using namespace std; const int inf = 0x3f3f3f3f;
const int vspot = 4e5 + ;
const int espot = 2e5 + ; struct node {
int to;
int next;
}e[vspot]; int N, M;
int cnt, linjie[vspot], pre[vspot], num;
int hit[vspot]; //hit[x]表示x号星球是否毁灭
int fin[vspot]; //fin记录被毁灭星球的顺序号数
int ans; int find( int x ) { return x==pre[x]?x:pre[x]=find(pre[x]); } void add( int x, int y )
{
e[cnt].to = y; e[cnt].next = linjie[x]; linjie[x] = cnt++;
e[cnt].to = x; e[cnt].next = linjie[y]; linjie[y] = cnt++;
} void init()
{
cnt = num = ;
ans = N;
memset( linjie, -, sizeof(linjie) );
for( int i = ; i <= N; i++ )
pre[i] = i;
} void read()
{
int x, y;
for ( int i = ; i < M; i++ )
{
scanf( "%d %d", &x, &y );
add( x, y );
} cin >> num;
for ( int i = ; i <= num; i++ )
{
scanf("%d", &x);
fin[i] = x;
hit[x] = ;
}
} void merge(int x)
{
int xr = find(x);
for ( int y = linjie[x]; y+; y = e[y].next )
if ( !hit[e[y].to] )
{
int yr = find(e[y].to);
if ( yr != xr )
{
pre[yr] = xr;
ans--;
}
}
} int main()
{
cin >> N >> M;
init();
read();
//先 画出图
for( int i = ; i < N; i++ )
{
if ( !hit[i] )
merge(i);
else
ans--; //一个星球被毁灭时,它本身就不算一个连通分量
}
fin[num+] = ans; //最后一个星球被毁灭后剩下的连通分量个数
//一个一个加点和加边
for ( int i = num; i > ; i-- )
{
hit[fin[i]] = ;
ans++; //将一个星球加回来时,相当于多了一个连通分量 merge(fin[i]);
fin[i] = ans;
}
////////////////用cout就会runtime error/////////////////////////
for( int i = ; i <= num+; i++ )
printf("%d\n",fin[i]); return ;
}

最新文章

  1. .net中xml文件的导入使用(包括创建xml和导入xml)
  2. table边框单线的实现方法
  3. LR学习笔记---参数设置 (转 温故而知新)
  4. sed使用的并不是完全的正则表达式
  5. java核心知识点学习----多线程间的数据共享和对象独立,ThreadLocal详解
  6. Android Capture Android System Audio
  7. web开发下的各种下载方法
  8. COB (Chip On Board) 製程介紹/簡介/注意事項 II
  9. 【CSS学习笔记】CSS初始化
  10. 关于web前端中遇到的html,css小知识点
  11. Shell-18--正则表达式
  12. google Guava包的ListenableFuture解析
  13. Spark 论文篇-Spark:工作组上的集群计算的框架(中英双语)
  14. tomcat 重启报错unregister mbean error javax.management.InstanceNotFoundException
  15. MapReduce (MRV1)设计理念与基本架构
  16. java刚開始学习的人常见的问题
  17. java 泛型--桥方法
  18. shell编程——日志输出的同时显屏
  19. Java入门系列-26-JDBC
  20. 【点分治】【FFT】CDOJ1562 Amaz1ng Prime

热门文章

  1. JDK9新特性实战:简化流关闭新姿势。
  2. 17.splash_case02
  3. SQLAlchemy的out join
  4. Walk Through Squares HDU - 4758 AC自动机+简单状压DP
  5. Python版本OpenCV安装配置及简单实例
  6. C++ 系列:static
  7. input 数值验证
  8. leetcode-137-只出现一次的数字②
  9. gdal在redhat4.4下安装
  10. Python学习day44-数据库(单表及多表查询)