zoukankan      html  css  js  c++  java
  • 并查集+时光倒流 || [JSOI2008]星球大战starwar || BZOJ 1015 || Luogu P1197

    题面:P1197 [JSOI2008]星球大战

    题解:

    坑点有点多啊,加上我本来就有点头昏脑涨,一道水题写了一万年。。

    并查集不支持拆开(但是可以撤销合并),只支持合并。所以把询问离线了,从最后状态到初状态开始一个个往当前图里加点。

    CZL:对于只有删除点/边而不增加点/边,且允许离线的题,可以考虑时光倒流,先建出最终情况,再倒着把点/边加回去。

    代码:

     1 #include<cstdio>
     2 using namespace std;
     3 inline int rd(){
     4     int x=0; char c=getchar();
     5     while(c<'0'||c>'9')c=getchar();
     6     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
     7     return x;
     8 }
     9 const int maxn=4e5+5,maxm=2e5+5;
    10 int N,M,fa[maxn],QUE[maxn],num_edge=0,edge_head[maxn];
    11 int u,v,K,cnt=0,f1,f2,ans[maxn];
    12 bool atkd[maxn];
    13 struct Edge{ int to,nx; }edge[maxm<<1];
    14 inline void Add_edge(int from,int to){
    15     edge[++num_edge].nx=edge_head[from];
    16     edge[num_edge].to=to;
    17     edge_head[from]=num_edge;
    18     return;
    19 }
    20 inline int getf(int n){
    21     if(fa[n]==n) return n;
    22     fa[n]=getf(fa[n]);
    23     return fa[n];
    24 }
    25 int main(){
    26     N=rd(); M=rd();
    27     for(int i=0;i<N;i++) fa[i]=i;
    28     for(int i=1;i<=M;i++){
    29         u=rd(); v=rd();
    30         Add_edge(u,v);
    31         Add_edge(v,u);
    32         f1=getf(u); f2=getf(v);
    33         if(f1!=f2) fa[f1]=f2;
    34     }
    35     for(int i=0;i<N;i++){
    36         if(fa[i]==i) ans[0]++;
    37         fa[i]=i;
    38     }
    39     K=rd();
    40     for(int i=1;i<=K;i++){
    41         QUE[i]=rd();
    42         atkd[QUE[i]]=1;
    43     }
    44     for(int i=0;i<N;i++)
    45         if(atkd[i]==0){
    46             for(int j=edge_head[i];j;j=edge[j].nx){
    47                 int y=edge[j].to;
    48                 if(atkd[y]) continue;
    49                 f1=getf(i); f2=getf(y);
    50                 if(f1!=f2) fa[f1]=f2;
    51             }
    52         }
    53     for(int i=0;i<N;i++)
    54         if(atkd[i]==0&&fa[i]==i) cnt++;
    55     for(int k=K;k>=1;k--){
    56         ans[k]=cnt;
    57         cnt++;
    58         int x=QUE[k];
    59         atkd[x]=0;
    60         for(int i=edge_head[x];i;i=edge[i].nx){
    61             int y=edge[i].to;
    62             if(atkd[y]) continue;
    63             f1=getf(x); f2=getf(y);
    64             if(f1!=f2){
    65                 cnt--;
    66                 fa[f1]=f2;
    67             }
    68         }
    69     }
    70     for(int i=0;i<=K;i++) printf("%d
    ",ans[i]);
    71     return 0;
    72 }
    View Code

    By:AlenaNuna

  • 相关阅读:
    集中式(SVN)和分布式(Git)版本控制系统的简单比较
    Mac 提示安装包已损坏
    React 获取 url 参数 —— this.props.match
    编写一个 Chrome 浏览器扩展程序
    webpack 配置学习笔记
    Python 进阶学习笔记
    Python 入门学习笔记
    (转)Unity3d各种坑
    unity3d 网页游戏客户端工程构建方案
    (转)在Unity3D的网络游戏中实现资源动态加载
  • 原文地址:https://www.cnblogs.com/AlenaNuna/p/11624822.html
Copyright © 2011-2022 走看看