bzoj 1015: [JSOI2008]星球大战starwar

 1 #include<cstdio>
 2 #include<iostream>
 3 #define M 2000000
 4 int cnt,fa[M],n,m,ans[M],k,f[M],a[M],head[M],next[2*M],u[2*M];
 5 int zhao(int a1)
 6 {
 7     if(a1==fa[a1])
 8       return a1;
 9     fa[a1]=zhao(fa[a1]);
10     return fa[a1];
11 }
12 void jia(int a1,int a2)
13 {
14      cnt++;
15      next[cnt]=head[a1];
16      u[cnt]=a2;
17      head[a1]=cnt;
18      return;
19 }
20 int main()
21 {
22     scanf("%d%d",&n,&m);
23     for(int i=1;i<=m;i++)
24       {
25         int a1,a2;
26         scanf("%d%d",&a1,&a2);
27         a1++;
28         a2++;
29         jia(a1,a2);
30         jia(a2,a1);
31       }
32     scanf("%d",&k);
33     for(int i=1;i<=k;i++)
34       {
35         int a1;
36         scanf("%d",&a1);
37         a[i]=++a1;
38         f[a1]=1;
39       }
40     for(int i=1;i<=n;i++)
41       fa[i]=i;
42     ans[k]=n-k;
43     for(int i=1;i<=n;i++)
44       if(!f[i])
45         for(int j=head[i];j;j=next[j])
46           if(!f[u[j]])
47             {
48               int b1=zhao(i),b2=zhao(u[j]);
49               if(b1!=b2)
50                {
51                  fa[b1]=b2;
52                  ans[k]--;
53                }
54             }
55     for(int i=k;i;i--)
56       {
57         f[a[i]]=0;
58         ans[i-1]=ans[i]+1;
59         for(int j=head[a[i]];j;j=next[j])
60           if(!f[u[j]])
61             {
62               int b1=zhao(a[i]),b2=zhao(u[j]);
63               if(b1!=b2)
64               {
65                 fa[b1]=b2;
66                 ans[i-1]--;
67               }
68             }
69       }
70     for(int i=0;i<=k;i++)
71       printf("%d\n",ans[i]);
72     return 0;
73 }

这个题离线倒着处理 先把所有删的删掉,然后倒着加,用并查集维护即可,当然题目中删掉的是点,别忘了啊!!

时间: 2024-10-13 15:11:45

bzoj 1015: [JSOI2008]星球大战starwar的相关文章

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

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

BZOJ 1015 JSOI2008 星球大战 starwar 并检查集合

标题效果:给定一个无向图.联通谋求块的数目,以及k一个点的破坏后每次:联通,块的数目 侧面和摧毁的地步全记录,我们可以做相反的. 需要注意的是该点不能算作破坏联通块 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 400400 using namespace std; struct abcd{ int to,next; }table[M];

BZOJ 1015 JSOI2008 星球大战 starwar 并查集

题目大意:给定一个无向图,求联通块个数,以及k次每次摧毁一个点后的:联通块个数 将边和摧毁的点全记录下来,反着做即可. 注意被摧毁的点不能算作联通块 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 400400 using namespace std; struct abcd{ int to,next; }table[M]; int hea

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

题目可以表述成:给定一个无向图G,每次删除它的一个点和与点相关的边集,每次询问该操作后图G的连通度(连通分量的个数).和上一题一样都是考察逆向思维,虽然删除点的做法不会,但是每次加点后询问连通度却是并查集的经典用法,所以答案可以逆过来推,具体做的时候每次加入一个点,将所有和这个点有边相连的点集合并,然后输出当前有多少个集合.细节部分需要注意的是由于点的数量十分庞大,邻接表是十分有必要的 #include<iostream> #include<cstdio> #include <

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 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重新造出了他的超级武

【BZOJ】1015: [JSOI2008]星球大战starwar(并查集)

http://www.lydsy.com/JudgeOnline/problem.php?id=1015 看了题解的囧T_T,一开始以为是求割点,但是想到割点不能统计.... 这题用并查集,思想很巧妙. 我们按照逆序建图,也就是从最后一个毁了的星球之后建图.然后从后往前走. 那么怎么统计联通块呢?很简单,我们开个数组记录没有被破坏的星球,然后每一次都将一个星球拿去访问他连接的其他点,看他们是否在一个联通块,如果不是,那么就将连接的那个点加入自己的联通块. #include <cstdio> #

【BZOJ】[JSOI2008]星球大战starwar

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

BZOJ 1015 JSOI2008 星球大战

题目的关键点在于读入后,倒着进行并查集操作.因为并查集不支持删点操作,所以读入后.按照顺序,逆着操作就可以了. #include <cstdio> #include <vector> #include <algorithm> using namespace std;   vector<int>Edge[400005]; int x,y,n,m; int k,ban[200005]; int fa[400005]; bool vis[400005]; int