bzoj1015: [JSOI2008]星球大战starwar 并查集+离线处理

题目传送门

这道题可以改为离线处理 倒着找答案 这样删点就变成加点了 有了这个思想题目就很好写了哇 23333

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=400007;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
int n,m,k,tot,sum;
int fa[M],ans[M],usd[M],in[M],first[M],q[M];
struct node{int to,next;}e[2*M];
void ins(int a,int b){sum++; e[sum].to=b; e[sum].next=first[a]; first[a]=sum;}
void insert(int a,int b){ins(a,b); ins(b,a);}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void add(int x){
    int p=find(x);
    for(int i=first[x];i;i=e[i].next){
        int now=e[i].to;
        if(usd[now]){
            int q=find(now);
            if(p!=q){fa[q]=p; tot--;}
        }
    }
}
int main()
{
    int x,y;
    n=read(); m=read();
    for(int i=0;i<n;i++) fa[i]=i;
    for(int i=1;i<=m;i++) x=read(),y=read(),insert(x,y);
    k=read();
    for(int i=1;i<=k;i++) q[i]=read(),in[q[i]]=1;
    for(int i=0;i<n;i++) if(!in[i]){
         tot++;
         add(i);
         usd[i]=1;
    }
    ans[k+1]=tot;
    for(int i=k;i;i--){
        tot++;
        add(q[i]);
        usd[q[i]]=1;
        ans[i]=tot;
    }
    for(int i=1;i<=k+1;i++) printf("%d\n",ans[i]);
    return 0;
}

时间: 2024-10-11 21:53:51

bzoj1015: [JSOI2008]星球大战starwar 并查集+离线处理的相关文章

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

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

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]; int hea

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

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

bzoj1015 [JSOI2008]星球大战starwar

1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 5134  Solved: 2328[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

BJOJ1015|星球大战starwar|并查集|离线操作

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

JSOI2008星球大战(并查集)

膜拜HZWER大牛的编码能力! 附上他的代码(我的代码不知为何一直莫名出错--) #include<iostream> #include<cstdio> #include<cstring> using namespace std; int tot,n,m,d,father[400001],head[400001],q[400001],ans[400001],cnt=1; bool used[400001],des[400001]; struct data{int to,

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--)