zoukankan      html  css  js  c++  java
  • 洛谷 P1197 [JSOI2008]星球大战

    题目描述

    很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系。

    某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。

    但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。

    现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通块的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)。

    输入输出格式

    输入格式:

     

    输入文件第一行包含两个整数,NN (1 < = N < = 2M1<=N<=2M) 和 MM (1 < = M < = 200,0001<=M<=200,000),分别表示星球的数目和以太隧道的数目。星球用 00 ~ N-1N1 的整数编号。

    接下来的 MM 行,每行包括两个整数 XX, YY,其中( 0 < = X <> Y0<=X<>Y 表示星球 xx 和星球 yy 之间有 “以太” 隧道,可以直接通讯。

    接下来的一行为一个整数 kk ,表示将遭受攻击的星球的数目。

    接下来的 kk 行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这 kk 个数互不相同,且都在 00 到 n-1n1 的范围内。

     

    输出格式:

     

    第一行是开始时星球的连通块个数。接下来的 KK 行,每行一个整数,表示经过该次打击后现存星球的连通块个数。

     

    输入输出样例

    输入样例#1: 复制
    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
    
    输出样例#1: 复制
    1
    1
    1
    2
    3
    3

    说明

    [JSOI2008]

    /*
    正难则反,倒着建边 
    */
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 210010
    using namespace std;
    int n,m,k,tot,sum;
    int vis[MAXN*2],ans[MAXN*2];
    int to[MAXN*2],net[MAXN*2],head[MAXN*2]; 
    int x[MAXN],y[MAXN],num[MAXN*2],fa[MAXN*2];
    int find(int x){
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)    fa[i]=i;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x[i],&y[i]);x[i]+=1;y[i]+=1;
            add(x[i],y[i]);add(y[i],x[i]);
        }
        scanf("%d",&k);
        for(int i=1;i<=k;i++){
            scanf("%d",&num[i]);num[i]+=1;
            vis[num[i]]=1;
        }
        for(int i=1;i<=m;i++){
            if(vis[x[i]]||vis[y[i]])    continue;
            int dx=find(x[i]),dy=find(y[i]);
            fa[dy]=dx;
        }
        sum=k+1;
        for(int i=1;i<=n;i++)
            if(find(i)==i&&!vis[i])    ans[sum]++;
        for(int i=k;i>=1;i--){
            ans[sum-1]=ans[sum];sum--;
            ans[sum]++;vis[num[i]]=0;
            for(int j=head[num[i]];j;j=net[j]){
                int dx=find(num[i]);
                int dy=find(to[j]);
                if(dx!=dy&&!vis[to[j]]){
                    fa[dy]=dx;ans[sum]--;
                }
            }
        }
        for(int i=1;i<=k+1;i++)
            cout<<ans[i]<<endl;
    }
    /*
    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
    */
  • 相关阅读:
    postgres column reference "id" is ambiguous
    网络 内网穿透frp
    odoo12 支付宝在线支付
    odoo 账号登录不上,重置密码也不管用
    odoo 取消保存提示
    聊聊redis分布式锁的8大坑 转载
    用 Keepalived+HAProxy 实现高可用负载均衡的配置方法 转载
    Nginx+keepalived 实现高可用,常用防盗链及动静分离配置 转载
    Git 实用技巧记录 转载:https://mp.weixin.qq.com/s/o6FvGfiG9b57xTeXlBzzQQ
    5 个冷门但非常实用的 Kubectl 使用技巧,99% 的人都不知道 https://mp.weixin.qq.com/s/h4_KRmsVSnlqCmIJh0altA
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/9829074.html
Copyright © 2011-2022 走看看