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]星球大战
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧 ...
随机推荐
- QT源码分析:QObject
QT框架里面最大的特色就是在C++的基础上增加了元对象系统(Meta-Object System),而元对象系统里面最重要的内容就是信号与槽机制,这个机制是在C++语法的基础上实现的,使用了函数.函数 ...
- 在使用Hanlp配置自定义词典时遇到的问题
要使用hanlp加载自定义词典可以通过修改配置文件hanlp.properties来实现.要注意的点是: 1. root根路径的配置: hanlp.properties中配置如下: #本配置文件中的路 ...
- lvm的一些特殊命令
pvscan --cache # 将lvm信息同步到其他节点 ......未完待续
- 自动化办公:xlsxwriter操作Excel
转载原链接:https://www.jianshu.com/p/d685cfaaeef7 1.安装 pip install xlsxwriter 2.操作一个简单的Excel文档 # 引入依赖模块 i ...
- [转帖]插曲:大白话带你认识Kafka
插曲:大白话带你认识Kafka 2019-11-18 21:58:27 从事Java 阅读数 2更多 分类专栏: java Kafaka 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA ...
- ACM算法锦集
一:知识点 数据结构: 1,单,双链表及循环链表 2,树的表示与存储,二叉树(概念,遍历)二叉树的 应用(二叉排序树,判定树,博弈树,解答树等) 3,文件操作(从文本文件中读入数据并输出到文本文 件中 ...
- rancher部署kubernets集群
docker的安装 先添加docker源 sudo apt update sudo apt install docker.io docker更换国内镜像 1.配置脚本如下: #!/bin/bashca ...
- nginx访问认证+目目录浏览
概述 在实际工作中,企业中有些网站,要求使用账号和密码才能访问,如网站后台.phpMyAdmin .Wiki 平台 等模块ngx_http_auth_basic_module 允许使用“HTTP基本认 ...
- Go ---- defer 和 return 执行的先后顺序
Go 中 defer 和 return 执行的先后顺序 多个defer的执行顺序为“后进先出”: defer.return.返回值三者的执行逻辑应该是:return最先执行,return负责将结果写入 ...
- EF6 + MySql 建立项目引用失败
EF6 + MySql 建立项目 步骤 在项目中使用” NuGet” 包添加 EntityFramework 和 MySql.Data ,如下图 (1) 在NuGet界面中的“浏览”选项卡 ...