[BZOJ 1015] [JSOI 2008] 星球大战starwar

1015: [JSOI2008]星球大战starwar

Time Limit: 3 SecMemory Limit: 162 MB

Description

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

Input

输入文件第一行包含两个整数,N (1 <= N <= 2M) 和M (1 <= M <= 200,000),分别表示星球的数目和以太隧道的数目。星球用0~N-1的整数编号。接下来的M行,每行包括两个整数X, Y,其中(0<=X<>Y

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

HINT

【题解】

本题数据范围一看,不能用tarjan,我也不会用TAT

于是就用并查集

看了看在在线搞好像会超时,然后就想到了离线来做。

先连着没有拆掉的边,然后求求连通块,倒过来做

每次删一条边倒过来就是添一条边。

然后并查集即可。

 1 #include<stdio.h>
 2 using namespace std;
 3 int a[400001],b[400001],c[400001],pre[400001],head[400001],next[400001],to[400001],tot,n,m,k;
 4 bool des[400001];
 5 int ans[400001];
 6 int getf(int x) {
 7     int r=x;
 8     while(r!=pre[r]) r=pre[r];
 9     int i=x,j;
10     while(i!=r) {
11         j=pre[i];
12         pre[i]=r;
13         i=j;
14     }
15     return r;
16 }
17 void addedge(int u,int v) {
18     ++tot;
19     to[tot]=v;
20     next[tot]=head[u];
21     head[u]=tot;
22 }
23 int main() {
24     scanf("%d%d",&n,&m);
25     for (int i=1;i<=n;++i) pre[i]=i;
26     for (int i=1;i<=m;++i) {
27         scanf("%d%d",&a[i],&b[i]);
28         a[i]++,b[i]++;
29         addedge(a[i],b[i]);
30         addedge(b[i],a[i]);
31     }
32     scanf("%d",&k);
33     for (int i=1;i<=k;++i) {
34         scanf("%d",&c[i]);
35         c[i]++;
36         des[c[i]]=1;
37     }
38     int ansx=n-k;
39     for (int i=1;i<=n;++i)
40         if(!des[i]) {
41             int f1=getf(i);
42             for (int j=head[i];j;j=next[j]) {
43                 if(!des[to[j]]) {
44                     int f2=getf(to[j]);
45                     if(f1!=f2) pre[f2]=f1, ansx--;
46                 }
47             }
48         }
49     ans[k+1]=ansx;
50     for (int i=k;i>=1;--i) {
51         ++ansx;
52         int f1=c[i];
53         for (int j=head[c[i]];j;j=next[j])
54             if(!des[to[j]]) {
55                 int f2=getf(to[j]);
56                 if(f1!=f2) pre[f2]=f1,--ansx;
57             }
58         ans[i]=ansx;
59         des[c[i]]=0;
60     }
61     for (int i=1;i<=k+1;++i) printf("%d\n",ans[i]);
62     return 0;
63 }

时间: 2024-12-24 06:57:20

[BZOJ 1015] [JSOI 2008] 星球大战starwar的相关文章

【BZOJ 1015】[JSOI2008]星球大战starwar

1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 3685  Solved: 1641[Submit][Status][Discuss] Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重

[JSOI 2008]星球大战starwar

Description 题库链接 给你一张 \(n\) 点, \(m\) 条边的无向图,每次摧毁一个点,问你剩下几个联通块. \(1\leq n\leq 2m,1\leq m\leq 200000\) Solution 删点不好操作,我们考虑倒序,变为加点.加边时,只考虑没删除的点间的连边,并查集维护. 是一道喜闻乐见的大水题. Code //It is made by Awson on 2018.2.27 #include <bits/stdc++.h> #define LL long lo

[BZOJ 1012] [JSOI 2008] 最大数maxnumber

1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 5094  Solved: 2276[Submit][Status][Discuss] Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度. 2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次

BZOJ 1570 JSOI 2008 Blue Mary的旅行 网络流

题目大意 给出一个有向图,每天每人只能做一次飞机.现在给出起点,终点,和需要走的人数,还有每条航线的限制人数,问最少多少天最慢的人到达终点. 思路 很明显是网络流的模型,至于如何去验证,其实连二分都不用,枚举最少天数,然后每次加一层边进行验证就行了. CODE #define _CRT_SECURE_NO_WARNINGS #include <queue> #include <cstdio> #include <cstring> #include <iostrea

BZOJ 1567 JSOI 2008 Blue Mary的战役地图 二维hash

题目大意:给出两个m*m的地图,问两个地图的最大子正方形矩阵的边长是多大. 思路:先对两个矩阵hash,然后枚举最大长度,从大到小枚举.把第一个矩阵的所有情况插到哈希表中,然后查询第二个矩阵的所有情况. 记住哈希表中的那些数组一定要开大点.. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 60 #define RA

BZOJ 1016 JSOI 2008 最小生成树计数 Kruskal+搜索

题目大意:给出一些边,求出一共能形成多少个最小生成树. 思路:最小生成树有非常多定理啊,我也不是非常明确.这里仅仅简单讲讲做法.关于定各种定理请看这里:http://blog.csdn.net/wyfcyx_forever/article/details/40182739 我们先做一次最小生成树.然后记录每一种长度的边有多少在最小生成树中,然后从小到大搜索,看每一种边权有多少种放法.然后全部的都算出来累乘就是终于的结果. CODE: #include <map> #include <cs

BZOJ 1015: [JSOI2008]星球大战starwar 并查集

1015: [JSOI2008]星球大战starwar Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重新造出了他的超级武器.凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球.由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来.现在,反抗军首领交给你一个任务:给出原

bzoj1015:1015: [JSOI2008]星球大战starwar

应该是全部读入之后再添加边用并查集就可以了. yyl用空间换时间.u[]v[]等将边预存起来. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--)

1015: [JSOI2008]星球大战starwar

1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 3001  Solved: 1321[Submit][Status] Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重新造出了他的超级武