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]星球大战
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧 ...
随机推荐
- 【Spring Boot学习之十二】mybatis3 分页打印sql日志
环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 参考: mybatis手册 Mybatis的插件 PageHelper 分页查询使用方法MyBatis中Like语句使 ...
- ECharts 避免变窄
var roomPercentChart = echarts.init(document.getElementById('room_percent')); function ajaxGetRoomPe ...
- phpmyadmin 显示被隐藏的表
点击后,会把这个表隐藏掉.有时候误点会莫名其妙. 点击数据库上的眼睛,能够显示被隐藏的表.
- LeetCode 912. 排序数组(Sort an Array) 43
912. 排序数组 912. Sort an Array 题目描述 每日一算法2019/6/15Day 43LeetCode912. Sort an Array
- SQL Server表水平分区
随着项目的运行时间越来越久,数据库的数据会越来越多,某些表因为数据量的变大查询起来会很慢,而且拥有大量数据的表整张表的数据都存于一个mdf文件中,不利于数据文件的维护和管理,我们一般都会通过优化sql ...
- cannot access org.springframework.core.io.InputStreamSouce
cannot access org.springframework.core.io.InputStreamSouce错误,把mian路径下main.iml文件备份一下,然后删除该文件,报错就会消失,但 ...
- GIL全局解释锁,死锁,信号量,event事件,线程queue,TCP服务端实现并发
一.GIL全局解释锁 在Cpython解释器才有GIL的概念,不是python的特点 在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势. 1.GIL介绍 ...
- Java线程本地存储ThreadLocal
前言 ThreadLocal 是一种 无同步 的线程安全实现 体现了 Thread-Specific Storage 模式:即使只有一个入口,内部也会为每个线程分配特有的存储空间,线程间 没有共享资源 ...
- Drools入门
文章转载自:http://cwqcwq.iteye.com/blog/397869 一.背景知识: 1.什么是规则引擎 Java规则引擎起源于基于规则的专家系统,而基于规则的专家系统又是专家系统的 ...
- C#设计模式之12:中介者模式
中介者模式 在asp.net core中实现进程内的CQRS时用mediatR是非常方便的,定义command,然后定义commandhandler,或者notification和notificati ...