P1197 [JSOI2008]星球大战[并查集+图论]
题目来源:洛谷
题目描述
很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系。
某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。
但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。
现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通块的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)。
输入输出格式
输入格式:
输入文件第一行包含两个整数,N (1<=N<=2M) 和 M (1<=M<=200,000),分别表示星球的数目和以太隧道的数目。星球用 0 ~ N-1 的整数编号。
接下来的 M 行,每行包括两个整数 X, Y,其中( 0<=X<>Y 表示星球 xx 和星球 yy 之间有 “以太” 隧道,可以直接通讯。
接下来的一行为一个整数 k ,表示将遭受攻击的星球的数目。
接下来的 k 行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这 k 个数互不相同,且都在 0 到 n−1的范围内。
输出格式:
第一行是开始时星球的连通块个数。接下来的 K 行,每行一个整数,表示经过该次打击后现存星球的连通块个数。
输入输出样例
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
2
3
3
说明
[JSOI2008]
这道题十分考验代码力和思维,需要对并查集和图论理解深入。
解析:
看到这题,我们如果按照题目意思理解,也可以很容易得到思路,只要建一个并查集,维护联通块就可以了。
但是根据题意,我们要从中删点,并在每次删完点之后统计联通块数量。
这就很令人头大了,我们知道,并查集并查集,合并容易删除难啊,这可怎么办呐?
没错,你可能已经想到了,既然合并比删除容易,那我们不妨倒转思路,逆向求解。
我们把题目改一下,姑且就叫它“反抗军重建计划”好了qwq:
很久以前,在一个遥远的星系,反抗军为了弥补之前帝国军队攻击的损失,开始了重建计划。
现在,反抗军首领交给你一个任务:给出将要重建的星球和重建计划中所有星球与其它星球之间的以太隧道,以尽量快的速度求出每重建完一个星球之后反抗军占据的星球的连通块的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)。
嘿嘿,这是不是简单多了?而且跟原题正好反过来,求得的解也正好逆序。
思路还是差不多,每次重建星球后,将该星球与计划中要联通的星球合并入并查集中,这道题就完成了。
但是这里要提一个点,关于邻接表。在本题中,我们当然可以把所有星球看做一个无向图,并用邻接表储存。
但是实际上我们可以这样理解:邻接表中的表头可以用于表示某一个将要重建的星球与其它星球的联通关系。
参考代码:
//反抗军重建计划qwq
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
#define N 100010
using namespace std;
//邻接表存图
struct node{
int next,ver,from;
}g[N<<];
int n,m,k,tot;
int head[N<<],ans[N<<],fa[N<<],b[N<<];
bool v[N<<];//是否需要重建
void add(int x,int y)
{
g[++tot].ver=y,g[tot].from=x;
g[tot].next=head[x],head[x]=tot;
}
int get(int x)
{
if(fa[x]==x) return x;
return fa[x]=get(fa[x]);
}
void merge(int x,int y)
{
x=get(x),y=get(y);
if(x!=y) fa[x]=y;
}
int main()
{
memset(v,,sizeof(v));
memset(b,,sizeof(b));
scanf("%d%d",&n,&m); for(int i=;i<n;i++) fa[i]=i;//初始化 for(int i=;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
scanf("%d",&k);
//需要重建的星球
for(int i=;i<=k;i++){
scanf("%d",&b[i]);
v[b[i]]=;//记录一下该星球需要重建
}
int cnt=n-k;
//还没重建,我们就先联通起来没被摧毁的星球
//如果两个星球都存在,也就是都不用重建时,合并
for(int i=;i<=*m;i++){
if(!v[g[i].ver]&&!v[g[i].from]&&get(g[i].from)!=get(g[i].ver)){
cnt--;merge(g[i].from,g[i].ver);
}
}
//从后往前将摧毁的星球建回去
ans[k+]=cnt;
for(int i=k;i>=;i--){
//统计联通块个数
cnt++;v[b[i]]=;
for(int j=head[b[i]];j;j=g[j].next){
if(!v[g[j].ver]&&get(g[j].from)!=get(g[j].ver)){
cnt--;merge(b[i],g[j].ver);
}
}
ans[i]=cnt;
}
for(int i=;i<=k+;i++) printf("%d\n",ans[i]);
return ;
}
P1197 [JSOI2008]星球大战[并查集+图论]的更多相关文章
- 洛谷P1197 [JSOI2008] 星球大战 [并查集]
题目传送门 星球大战 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这 ...
- P1197 [JSOI2008]星球大战 并查集 反向
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧 ...
- 洛谷 P1197 [JSOI2008]星球大战——并查集
先上一波题目 https://www.luogu.org/problem/P1197 很明显删除的操作并不好处理 那么我们可以考虑把删边变成加边 只需要一波时间倒流就可以解决拉 储存删边顺序倒过来加边 ...
- JSOI2008 星球大战 [并查集]
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧 ...
- [bzoj1015][JSOI2008]星球大战——并查集+离线处理
题解 给定一张图,支持删点和询问连通块个数 按操作顺序处理的话要在删除点的同时维护图的形态(即图具体的连边情况),这是几乎不可做的 我们发现,这道题可以先读入操作,把没删的点的边先连上,然后再倒序处理 ...
- P1197 [JSOI2008]星球大战(并查集判断连通块+正难则反)
P1197 [JSOI2008]星球大战(并查集判断连通块+正难则反) 并查集本来就是连一对不同父亲的节点就的话连通块就少一个. 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统 ...
- html5 canvas程序演示--P1197 [JSOI2008]星球大战
html5 canvas程序演示--P1197 [JSOI2008]星球大战 <!doctype html> <html> <head> <meta char ...
- Bzoj1015/洛谷P1197 [JSOI2008]星球大战(并查集)
题面 Bzoj 洛谷 题解 考虑离线做法,逆序处理,一个一个星球的加入.用并查集维护一下连通性就好了. 具体来说,先将被消灭的星球储存下来,先将没有被消灭的星球用并查集并在一起,这样做可以路径压缩,然 ...
- 【反向并查集、联通图】P1197 [JSOI2008]星球大战
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧 ...
随机推荐
- (IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
参考博客: https://www.cnblogs.com/xiao987334176/p/9056511.html 内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yi ...
- 搭建kafaka集群
服务器环境准备 使用vm虚拟三个linux主机 192.168.212.174 192.168.212.175 192.168.212.176 Zookeeper集群环境搭建 1.每台服务器节点上安装 ...
- Python代码约定
建议遵守以下约定: 使用 4 个空格来缩进 永远不要混用空格和制表符 在函数之间空一行 在类之间空两行 字典,列表,元组以及参数列表中,在 , 后添加一个空格.对于字典,: 后面也添加一个空格 在赋值 ...
- ETCD服务
ETCD 简介 ETCD是一个开源的.分布式的键值对数据存储系统,由Go语言实现,用于存储key-value键值对,同时不仅仅是存储,主要用途是提供共享配置及服务发现,使用Raft一致性算法来管理高度 ...
- 构建helm chart应用
使用helm命令创建基础目录 helm create t2cp [root@node04 ~]# tree t2cp t2cp ├── charts ├── Chart.yaml ├── templa ...
- 分享AWS网站
1.AWS服务运行状况检测网站: https://status.amazonaws.cn/ 2.AWS架构白皮书:https://aws.amazon.com/cn/architecture/?a ...
- 二 python并发编程之多进程实现
一 multiprocessing模块介绍 二 process类的介绍 三 process类的使用 四 守护进程 五 进程同步(锁) 六 队列 七 管道 八 共享数据 九 信号量 十 事件 十一 进程 ...
- js流程控制语句(三)
如果在语句中需要声明变量时:最好给他们赋予初始类型值[js中变量声明使用var属于弱类型声明,若只声明则均表示为undefined,在后面语句计算中可能会产生错误计算];相应的类型变量需要如下方式进行 ...
- 美国LangeEylandt长岛
LangeEylandt n.长岛(美国) 纽约长岛 纽约长岛 (LongIsland)是北美洲在大西洋内的一个岛,最早追溯到十七世纪的1650年被命名为Lange Eylandt [1] ,位于北美 ...
- Alpha_6
一. 站立式会议照片 二. 工作进展 (1) 昨天已完成的工作 a. 修改设计图的小毛病 b. 补签卡页面 c. 实现我的,我的卡包,卡片细节功能页面,并可预览 d. 已实现“番茄钟_数据统计”页面和 ...