• 洛谷P1197 [JSOI2008]星球大战


    P1197 [JSOI2008]星球大战

    题目描述

    很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系。某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。

    但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通快的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)。

    输入输出格式

    输入格式:

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

    接下来的M行,每行包括两个整数X, Y,其中(0<=X<>Y<N),表示星球X和星球Y之间有以太隧道。注意所有的以太隧道都是双向的。

    接下来一行是一个整数K,表示帝国计划打击的星球个数。

    接下来的K行每行一个整数X,满足0<=X<N,表示帝国计划打击的星球编号。帝国总是按输入的顺序依次摧毁星球的。

    输出格式:

    输出文件的第一行是开始时星球的连通块个数。

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

    输入输出样例

    输入样例#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<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 400001
    using namespace std;
    struct node{
        int from,to,pre;
    }e[maxn];
    int n,m,k,num;
    int fa[maxn],head[maxn],fire[maxn],tot[maxn];
    bool use[maxn];
    void Insert(int from,int to){
        e[++num].to=to;
        e[num].from=from;
        e[num].pre=head[from];
        head[from]=num;
    }
    int find(int x){
        if(fa[x]==x)return x;
        return fa[x]=find(fa[x]);
    }
    int main(){
        scanf("%d%d",&n,&m);int x,y;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            Insert(x,y);Insert(y,x);
        }
        scanf("%d",&k);
        for(int i=1;i<=k;i++){
            scanf("%d",&x);
            use[x]=1;fire[i]=x;
        }
        for(int i=0;i<n;i++)fa[i]=i;
        int block=n-k,kk=0;
        for(int i=1;i<=num;i++){
            if(!use[e[i].from]&&!use[e[i].to]&&find(e[i].from)!=find(e[i].to)){
                block--;
                fa[find(e[i].from)]=find(e[i].to);
            }
        }
        tot[++kk]=block;
        for(int i=k;i>=1;i--){
            block++;
            use[fire[i]]=0;
            for(int j=head[fire[i]];j;j=e[j].pre){
                if(!use[e[j].to]&&find(fire[i])!=find(e[j].to)){
                    block--;
                    fa[find(fire[i])]=find(e[j].to);
                }
            }
            tot[++kk]=block;
        }
        for(int i=kk;i>=1;i--)printf("%d
    ",tot[i]);
        return 0;
    }
  • 相关阅读:
    websocket使用nginx作为反向代理
    curl模拟http发送get或post接口测试
    linux tail -f messages查看控制台失败
    shell中使用>/dev/null 2>&1 丢弃信息
    mysql备份与还原
    计算机中RAM和ROM
    *C语言有关指针的变量声明中的几个易错点
    五种存储变量补充~作用域和存储时期
    typedef和#define的简单比较
    fopen()函数参数
  • 原文地址:https://www.cnblogs.com/thmyl/p/7725519.html
Copyright © 2020-2023  润新知