题目描述

很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系。

某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。

但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。

现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通块的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)。

输入输出格式

输入格式:

输入文件第一行包含两个整数, N( 1<=N<=2M ) 和 M ( 1<=M<=200,000 ),分别表示星球的数目和以太隧道的数目。星球用 0 ~ N-1 的整数编号。

接下来的 M 行,每行包括两个整数 X , Y ,其中(0<=X<>Y 表示星球 x 和星球 y之间有 “以太” 隧道,可以直接通讯。

接下来的一行为一个整数  ,表示将遭受攻击的星球的数目。

接下来的 k 行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这 k个数互不相同,且都在 0到 n−1 的范围内。

输出格式:

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

输入输出样例

输入样例#1:

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
输出样例#1:

1
1
1
2
3
3

说明

[JSOI2008]

删边不如加边--LVYOUYW。

当我们看到联通块,我们眼前一亮,脑海里闪过了并查集。可是我们如何维护每次删边的操作,看起来很复杂的样子。

我们不妨换个思路,先求最后所有边都被摧毁的情况,也就求出了最后一种情况的答案,再一点点的加边。因为我们会加边操作,不会删边操作啊!于是,这个离线算法就确定了。

具体操作:断边、连边,我们听起来是图论的样子,但在本题中实质就是在并查集中将他们合并/拆散。最开始的情况我们先用邻接表存好,而是否在集合的信息用并查集维护。

这样,当我们再读入需要断边的消息时,不断,而是默默记录。我们首先要意识到,加边联通块减少,断边联通块增多。这样我们就可以倒着遍历需要断的节点,并遍历与其相连的所有边。

code

 #include<cstdio>
#include<algorithm> using namespace std; int n,m,cnt,tot,x,y,k,head[],ans[],f[],flag[],mark[];
struct node{
int to,next,from;
}edge[]; int getf(int x)
{
if(f[x]==x) return f[x];
return f[x]=getf(f[x]);
} void merge(int x,int y)
{
int pp=getf(x);
int qq=getf(y);
if(pp!=qq) f[qq]=pp;
} void add(int x,int y)
{
edge[++cnt].to=y;
edge[cnt].from=x;//不同于普通的邻接表,这里我们多维护了一个信息。
edge[cnt].next=head[x];
head[x]=cnt;
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) f[i]=i,head[i]=-;
//初始化很重要!节点编号从0开始,head要设为-1
//另外注意初始化的位置(滑稽
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
scanf("%d",&k);
for(int i=;i<=k;i++)
{
scanf("%d",&x);
flag[x]=;
mark[i]=x;
}
tot=n-k;//开始各点为一独立的联通块
for(int i=;i<=*m;i++)
{
if(!flag[edge[i].to]&&!flag[edge[i].from]&&getf(edge[i].to)!=getf(edge[i].from))
merge(edge[i].to,edge[i].from),tot--;
//每连一边,联通块便减少一点点
}
ans[k+]=tot;
for(int i=k;i>=;i--)
{
tot++;int p=mark[i];flag[p]=;
//当前未连时的点是一个独立的联通块
for(int j=head[p];j!=-;j=edge[j].next)
{//head意义改变,这里也就变了,注意!
if(!flag[edge[j].to]&&getf(edge[j].to)!=getf(p))
tot--,merge(edge[j].to,p);
}
ans[i]=tot;
}
for(int i=;i<=k+;i++) printf("%d\n",ans[i]);
return ;
}

附:并查集求联通块个数

https://blog.csdn.net/rcy_zhu/article/details/77622043

Luogu P1197 [JSOI2008]星球大战 By cellur925的更多相关文章

  1. luogu P1197 [JSOI2008]星球大战

    题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道 ...

  2. [Luogu 1197] JSOI2008 星球大战

    [Luogu 1197] JSOI2008 星球大战 我算是真的沦为联赛选手了. 并查集裸题. 比较麻烦的是删点. 但是从后往前加点就好操作很多. 所以考虑离线,先存图,然后没被删的点之间,有边就合并 ...

  3. html5 canvas程序演示--P1197 [JSOI2008]星球大战

    html5 canvas程序演示--P1197 [JSOI2008]星球大战 <!doctype html> <html> <head> <meta char ...

  4. P1197 [JSOI2008]星球大战(并查集判断连通块+正难则反)

    P1197 [JSOI2008]星球大战(并查集判断连通块+正难则反) 并查集本来就是连一对不同父亲的节点就的话连通块就少一个. 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统 ...

  5. 洛谷P1197 [JSOI2008] 星球大战 [并查集]

    题目传送门 星球大战 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这 ...

  6. P1197 [JSOI2008]星球大战——链式前向星+并查集

    https://www.luogu.org/problem/P1197 这道题算是关闭农场的加强版吧,数据有点大,矩阵存不下: 也是记录删点操作,从后往前加边: 先将每个点都算成一个连通块,然后每连一 ...

  7. 洛谷 P1197 [JSOI2008]星球大战——并查集

    先上一波题目 https://www.luogu.org/problem/P1197 很明显删除的操作并不好处理 那么我们可以考虑把删边变成加边 只需要一波时间倒流就可以解决拉 储存删边顺序倒过来加边 ...

  8. P1197 [JSOI2008]星球大战

    题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道 ...

  9. P1197 [JSOI2008]星球大战[并查集+图论]

    题目来源:洛谷 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球 ...

随机推荐

  1. python手记(53)

    import sys import pygame from pygame.locals import * import time import math pygame.init() screen=py ...

  2. 我所写的CNN框架 VS caffe

    我所写的CNN框架 VS caffe 一个月前.自己模仿caffe实现了一个卷积神经网络的框架. 同样点 1无缝支持CPU和GPU模式,GPU模式使用cuda实现. 不同点 1我的CNN不依赖与不论什 ...

  3. 使用JS对select标签进行联动选择

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  4. Android项目之HomeHealth基础学习2:Service

    一. Service简单介绍 Service是android 系统中的四大组件之中的一个(Activity.Service.BroadcastReceiver.ContentProvider),它跟A ...

  5. asp.net mvc + javascript生成下载文件

    近期做的是对现有项目进行重构.WEB FROM改成MVC,其实也算是推倒重来了. 里面有一个导出功能,将数据输出成txt文件,供下载.原先的做法是有一个隐藏的iframe,在这个iframe的页面中设 ...

  6. 使用jdbc对mysql进行增删改查

    建立数据库和数据表 CREATE DATABASE `mysqlTest` DEFAULT CHARACTER SET utf8; CREATE TABLE `test` ( `id` ) NOT N ...

  7. MVC优缺点

    1.通过把项目分成model view和controller,使得复杂项目更加容易维护. 2.没有使用view state和服务器表单控件,可以更方便的控制应用程序的行为 3.应用程序通过contro ...

  8. java jdbc/ojdbc 链接oracle的三种方式

    方法一:使用service_name 连接oracle  jdbc:oracle:thin:@//:/<service_name> 例如: jdbc:oracle:thin:@//10.1 ...

  9. XMU C语言程序设计实践(1)

    题目: 任务1:英雄出世 炎热的夏天午后,小明正在百无聊赖地写c语言程序.忽然,电脑屏幕一阵抖动,浮现下面18×18个看似杂乱无章的数字: 32,  32,  32,  32,  32,  32,  ...

  10. JPEG库在Linux系统下的编译和移植【转】

    本文转载自: 这篇文章介绍了jpeg库在Linux系统下的编译和移植,经过了亲自的验证,编译首先需要准备以下资源:jpegsrc.v6b.tar.gz(jpeg库),libtool-1.5.26.ta ...