P1197 [JSOI2008]星球大战 [删边求连通块个数]
题目描述
很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系。
某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。
但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。
现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通块的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)。
输入格式
输入文件第一行包含两个整数,n,mn,m,分别表示星球的数目和以太隧道的数目。星球用 0 \sim n-10∼n−1 的整数编号。
接下来的 mm 行,每行包括两个整数 x,yx,y,表示星球 xx 和星球 yy 之间有 “以太” 隧道,可以直接通讯。
接下来的一行为一个整数 kk ,表示将遭受攻击的星球的数目。
接下来的 kk 行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这 kk 个数互不相同,且都在 00 到 n-1n−1 的范围内。
输出格式
第一行是开始时星球的连通块个数。接下来的 kk 行,每行一个整数,表示经过该次打击后现存星球的连通块个数。
输入输出样例
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
思路
对于删边求连通块个数问题, 就我遇到的来说,一般可以考虑暴搜,并查集和tarjan来做.
对于此题来说, 显然用并查集做更简单, 考虑用并查集实现.
由于并查集写删边的码量很大很复杂, 但是建边很容易, 所以考虑反向处理.
首先, 令所有点都是单独的连通块, 因为炸掉了就不能参与构成连通块了, 所以先处理出剩下了多少可以操作的连通块.
令最终态就是此时的连通块个数, 接着反向加点连边.
每加上一个点, 连通块的个数肯定就要 + 1 , 然后遍历炸点之前它可以连的边, 如果连上一个连通块, 那么对应的此时连通块个数就要 - 1 ;
最后就可以处理出每个点炸点前的连通块数量, 反向输出即可.
CODE
#include <bits/stdc++.h>
#define dbg(x) cout << #x << "=" << x << endl
#define eps 1e-8
#define pi acos(-1.0) using namespace std;
typedef long long LL; template<class T>inline void read(T &res)
{
char c;T flag=;
while((c=getchar())<''||c>'')if(c=='-')flag=-;res=c-'';
while((c=getchar())>=''&&c<='')res=res*+c-'';res*=flag;
} namespace _buff {
const size_t BUFF = << ;
char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
char getc() {
if (ib == ie) {
ib = ibuf;
ie = ibuf + fread(ibuf, , BUFF, stdin);
}
return ib == ie ? - : *ib++;
}
} int qread() {
using namespace _buff;
int ret = ;
bool pos = true;
char c = getc();
for (; (c < '' || c > '') && c != '-'; c = getc()) {
assert(~c);
}
if (c == '-') {
pos = false;
c = getc();
}
for (; c >= '' && c <= ''; c = getc()) {
ret = (ret << ) + (ret << ) + (c ^ );
}
return pos ? ret : -ret;
} const int maxn = 2e5 + ; int cnt, head[maxn << ], edge[maxn << ], nxt[maxn << ], from[maxn << ];
bool vis[maxn << ];
int a[maxn << ], ans[maxn << ],fa[maxn << ];
int tot,n,m,x,y,k; void BuildGraph(int u, int v) {
cnt++;
edge[cnt] = v;
from[cnt] = u;
nxt[cnt] = head[u];
head[u] = cnt;
} int fid(int x) {
return x == fa[x] ? x : fa[x] = fid(fa[x]);
} int main()
{
scanf("%d %d",&n, &m);
for ( int i = ; i <= m; ++i ) {
int u, v;
scanf("%d %d",&u, &v);
BuildGraph(u, v);
BuildGraph(v, u);
}
scanf("%d",&k);
for ( int i = ; i <= k; ++i ) {
int x;
scanf("%d",&x);
vis[x] = ;
a[i] = x;
}
for ( int i = ; i <= n; ++i ) {
fa[i] = i;
}
tot = n - k;
for ( int i = ; i <= * m; ++i ) {
if(!vis[from[i]] && !vis[edge[i]]) {
if(fa[fid(from[i])] != fa[fid(edge[i])]) {
tot--;
fa[fid(from[i])] = fa[fid(edge[i])];
}
}
}
ans[k+] = tot;
for ( int i = k; i >= ; --i ) {
int x = a[i];
vis[x] = ;
tot++;
for ( int j = head[x]; j; j = nxt[j] ) {
if(vis[edge[j]] == && fa[fid(x)] != fa[fid(edge[j])]) {
tot--;
fa[fid(x)] = fa[fid(edge[j])];
}
}
ans[i] = tot;
}
for ( int i = ; i <= k+; ++i ) {
printf("%d\n",ans[i]);
}
return ;
}
P1197 [JSOI2008]星球大战 [删边求连通块个数]的更多相关文章
- DFS:POJ1562-Oil Deposits(求连通块个数)
Oil Deposits Time Limit: 1000MS Memory Limit: 10000K Description The GeoSurvComp geologic survey com ...
- 求连通块个数 - BFS、DFS、并查集实现
本文基于leetcode的200.岛屿数量(题目
- P1197 [JSOI2008]星球大战(并查集判断连通块+正难则反)
P1197 [JSOI2008]星球大战(并查集判断连通块+正难则反) 并查集本来就是连一对不同父亲的节点就的话连通块就少一个. 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统 ...
- html5 canvas程序演示--P1197 [JSOI2008]星球大战
html5 canvas程序演示--P1197 [JSOI2008]星球大战 <!doctype html> <html> <head> <meta char ...
- 洛谷P1197 [JSOI2008] 星球大战 [并查集]
题目传送门 星球大战 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这 ...
- Luogu P1197 [JSOI2008]星球大战 By cellur925
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧 ...
- P1197 [JSOI2008]星球大战[并查集+图论]
题目来源:洛谷 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球 ...
- P1197 [JSOI2008]星球大战
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道 ...
- luogu P1197 [JSOI2008]星球大战
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道 ...
随机推荐
- Python经典算法-快速幂
快速幂 问题描述: 计算a ** n % b 其中a.b和n都是32位的非负整数 即求a的n次方对b的余数 问题示例: 例如:2**31%3=2 --- 代码实现如下 class Solution: ...
- 三句话搞定FireDAC连接池
form上拖入: FDManager1: TFDManager; FDConnection1: TFDConnection; //初始化连接池procedure TForm1.InitDBPool;b ...
- 聊聊SpringBoot | 第一章:快速搭建SpringBoot第一个应用
快速搭建SpringBoot第一个应用 1.简介 本章仅介绍如何快速搭建第一个SpringBoot应用,细节内容下一章再做讲解,如果有需要,各位可以直接到Spring官网去了解. 从 Spring B ...
- Linux学习笔记-centos查看版本号和内核信息
1.查看centos系统版本号: 打开终端窗口: cat /etc/redhat-release 2.查看Linux内核版本信息: uname -a 或者 在图形化桌面右上角点开设置,在设置窗口选择详 ...
- sass css样式:@for循环、样式变量与#{} 变量插值
/* sass 可以用写JS的思想来写CSS代码 * #{} 用来插值,大括号中填写需要插入的变量 * @for 变量 from ...
- 曹工说Spring Boot源码(14)-- AspectJ的Load-Time-Weaving的两种实现方式细细讲解,以及怎么和Spring Instrumentation集成
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- python中map()和dict()的用法
map()用法 map()是python的内置函数,会根据提供的函数对指定序列做映射. 语法: map(func, iter, ...) 其中func为一个功能函数,iter表示可迭代参数序列.map ...
- 优雅地关闭worker进程
关闭nginx两种方式 nginx -s stop 立即停止nginx进程 nginx -s quit 优雅地关闭worker进程 开始优雅的关闭worker进程后 01设置定时器 worker_ ...
- python 中的反斜杠匹配的问题
关于反斜杠的匹配问题可以参考: https://www.cnblogs.com/mzc1997/p/7689235.html 文章中提出了两个概念: 字符串转义和正则转义,我觉得是理解反斜杠的关键所在 ...
- Springboot全局事务处理
什么是全局事务 Spring Boot(Spring)事务是通过aop(aop相关术语:通知(Advice).连接点(Joinpoint).切入点(Pointcut).切面(Aspect).目标(Ta ...