1015: [JSOI2008]星球大战starwar

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 5139  Solved: 2332
[Submit][Status][Discuss]

Description

  很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系。某一天,凭着一个偶然的
机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直
接或间接地连接。 但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划
地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。现在,反抗军首
领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每
一次打击之后反抗军占据的星球的连通快的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则
这两个星球在同一个连通块中)。

Input

  输入文件第一行包含两个整数,N (1  < =  N  < =  2M) 和M (1  < =  M  < =  200,000),分别表示星球的
数目和以太隧道的数目。星球用 0 ~ N-1的整数编号。接下来的M行,每行包括两个整数X, Y,其中(0 < = X <> 
Y 表示星球x和星球y之间有“以太”隧道,可以直接通讯。接下来的一行为一个整数k,表示将遭受攻击的星球的
数目。接下来的k行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这k个数互不相同,且都在0到n-1的范
围内。

Output

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

Sample Input

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

Sample Output

1
1
1
2
3
3
 
逆向思维的典型应用。
给定一张图,支持删点和询问连通块个数,按操作顺序处理的话要在删除点的同时维护图的形态(即图具体的连边情况),这是几乎不可做的,我们发现,这道题可以先读入操作,把没删的点的边先连上,然后再倒序处理操作,这样的话从删点变成了加点,而且只要维护连通块的数量,用并查集可以快速的解决这个问题。
 
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
using namespace std;
int n,m,d,len,tot,q[],a[],f[],vis[],used[],ans[];
struct node{int y,next;}e[];
inline int read()
{
int x=,f=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-; ch=getchar();}
while(isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
void insert(int xx,int yy)
{
e[++len].next=a[xx];
a[xx]=len;
e[len].y=yy;
}
int find(int x)
{return f[x]==x?x:f[x]=find(f[x]);}
void add(int x)
{
int pp=find(x),qq;
for(int i=a[x];i;i=e[i].next)
{
if(used[e[i].y])
{
qq=find(e[i].y);
if(pp!=qq) {tot--; f[qq]=pp;}
}
}
}
int main()
{
n=read(); m=read();
for(int i=;i<n;i++) f[i]=i;
for(int i=;i<=m;i++)
{
int x=read(),y=read();
insert(x,y);
insert(y,x);
}
d=read();
for(int i=;i<=d;i++)
{
q[i]=read();
vis[q[i]]=;
}
for(int i=;i<n;i++)
if(!vis[i])
{
tot++;
add(i);
used[i]=;
}
ans[d+]=tot;
for(int i=d;i>;i--)
{
tot++;
add(q[i]);
used[q[i]]=;
ans[i]=tot;
}
for(int i=;i<=d+;i++) printf("%d\n",ans[i]);
return ;
}

最新文章

  1. Javascript实现页面加载完成后自动刷新一遍清除缓存文件
  2. tcpdump抓SQL[转]
  3. 学习iOS前我们需要知道的事情
  4. 调用newtonsoft.json反序列出错
  5. 1.6Linux设备驱动
  6. 传说中的WCF(9):流与文件传输
  7. iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数
  8. 框架搭建资源 (二) 添加M(模型)
  9. GNU/Linux-MariaDB
  10. 图像处理------Canny边缘检测
  11. linux 添加ssh和开启ssh服务apt管理的ubuntu
  12. Docker常规防止容器自动退出
  13. nginx 文档链接
  14. 43.纯 CSS 绘制一个充满动感的 Vue logo
  15. noip第33课作业
  16. Hdu4687 Boke and Tsukkomi
  17. 结束autocad异常进程
  18. TED_Topic10:The case for engineering our food
  19. 【转】Java并发编程:线程池的使用
  20. CentOS 6.9设置阿里云源/163源

热门文章

  1. 用java网络编程中的TCP方式上传文本文件及出现的小问题
  2. VGGNet网络结构
  3. 常用的两个PHP类
  4. LINUX TCP套接字详细配置
  5. Linux 服务器的那些性能参数指标
  6. Angular2常用命令
  7. XMemcached使用经历
  8. ubuntu 环境变量配置
  9. POJ 2823 Sliding Window(单调队列入门题)
  10. Java-Runoob:Java 简介