【bzoj1015】【JSOI2008】【星球大战】【并查集+离线】

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

题解:显然我们能够用并查集维护联通关系。然后我们把全部操作存下来,倒着做。把删边改成加边就可以。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int fa[1000001],point[1000001],next[1000001],cnt,a[1000001],aa[1000001];
int n,m,x,y,ans,q;
bool f[1000001];
struct use{
    int st,en;
}e[10000001];
inline int find(int x)
{
    if (fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
inline void add(int x,int y)
{
   next[++cnt]=point[x];point[x]=cnt;
   e[cnt].st=x;e[cnt].en=y;
}
int main()
{
    scanf("%d%d",&n,&m);ans=n;
    memset(f,true,sizeof(f));
    for (int i=0;i<=n-1;i++) fa[i]=i;
    for (int i=1;i<=m;i++)
      {
        int r1,r2;
        scanf("%d%d",&x,&y);
        r1=find(x);r2=find(y);
        if (r1!=r2) {fa[r1]=r2;ans--;}
        add(x,y);add(y,x);
      }
    cout<<ans<<endl;
    ans=n;scanf("%d",&q);
    for (int i=1;i<=q;i++)
      {
        scanf("%d",&x);
        f[x]=false;
        a[i]=x;
      }
    ans-=q;
    for (int i=0;i<=n-1;i++) fa[i]=i;
    for (int i=1;i<=cnt;i++)
      if (f[e[i].st]&&f[e[i].en])
       {
         int r1,r2;
         r1=find(e[i].st);r2=find(e[i].en);
         if (r1!=r2) {fa[r1]=r2;ans-=1;}
       }
    aa[q]=ans;
    for (int i=q;i>=1;i--)
     {
        int u,r1,r2;
        ans+=1;
        u=a[i];
        f[u]=true;
        for (int j=point[u];j;j=next[j])
          {
              if (f[e[j].st]&&f[e[j].en])
              {
               r1=find(e[j].st);r2=find(e[j].en);
               if (r1!=r2) {fa[r1]=r2;ans-=1;}
              }
          }
        aa[i-1]=ans;
     }
    for (int i=1;i<=q;i++)
       printf("%d\n",aa[i]);
}
时间: 2024-10-17 17:55:44

【bzoj1015】【JSOI2008】【星球大战】【并查集+离线】的相关文章

BZOJ 1015 星球大战 并查集+离线

这道题说来真是艰辛,从一开始的RE,到RE,到刚刚的WA,再到AC. 这只能说明我进步的历程,还有我需要不断的加强努力.这道题思路不难,从很久前在黑书中并查集一节就能找到解题的踪影,因为并查集只能并,分不了,所以我们就得离线,倒过来写.只不过这道题真的得审好题目,它问的是剩下的星球中有多少个连通分量,不要搞错了.大概就是这个样子了,加油. 1 #include<cstdio> 2 #include<iostream> 3 #define rep(i,j,k) for(int i=

[JSOI2008]星球大战——并查集+逆向思维

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

ACM学习历程—SNNUOJ 1110 传输网络((并查集 &amp;&amp; 离线) || (线段树 &amp;&amp; 时间戳))(2015陕西省大学生程序设计竞赛D题)

Description Byteland国家的网络单向传输系统可以被看成是以首都 Bytetown为中心的有向树,一开始只有Bytetown建有基站,所有其他城市的信号都是从Bytetown传输过来的.现在他们开始在其他城市陆 续建立了新的基站,命令“C x“代表在城市x建立了一个新的基站,不会在同一个城市建立多个基站:城市编号为1到n,其中城市1就是首都Bytetown.在建立基站的过程中他们还 会询问某个城市的网络信号是从哪个城市传输过来的,命令”Q x“代表查询城市x的来源城市. Inpu

BZOJ1015[JSOI2008]星球大战starwar[并查集]

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

BZOJ1015 [JSOI2008]星球大战starwar(并查集)

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

【并查集】bzoj1015 [JSOI2008]星球大战starwar

倒着处理删点,就变成了加点,于是并查集. #include<cstdio> using namespace std; #define N 400001 int fa[N],kill[N],rank[N],n,m,q; bool hav[N]; int next[N],first[N],v[N],en,x,y,anss[N],cnt; void AddEdge(int U,int V) { v[++en]=V; next[en]=first[U]; first[U]=en; } int find

【JSOI2008】星球大战[并查集]

[JSOI2008]星球大战 决定再做一道并查集水题.... 正难则反 现将要攻击的星球都读入 然后记录已损坏 再将能连的都连上 然后倒着做 就是套路了QAQ 第一次交的代码死于没有认真读题...编号是从0开始的 #include<bits/stdc++.h> using namespace std; const int N=4e5+5,M=2e5+5,inf=0x3f3f3f3f,P=19650827; int n,m,k,cnt=0,ans[N],a[N]; bool broken[N];

bzoj1015 [JSOI2008]星球大战starwar

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

zoj 3261 Connections in Galaxy War(并查集+离线逆向操作)

 题目:给出一些点,每个点有权值,然后有一些边,相连.无向的.然后有一些操作 query a.表示从a出发的能到达的所有点权值最大的点的编号(相同取编号最小,而且权值要比自己大) destory a,b 表示删除连接a,b的边 思路并查集,但是要逆向处理,所以先离线读入,从后向前处理,于是对于destroy操作,等价于连接两个点的操作,然后对于每个询问输出即可 #include<cstdio> #include<cstring> #include<cmath> #i