zoukankan      html  css  js  c++  java
  • bzoj1015星球大战(并查集+离线)

    1015: [JSOI2008]星球大战starwar

    Time Limit: 3 Sec  Memory Limit: 162 MB
    Submit: 5572  Solved: 2563

    Description

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

    Input

      输入文件第一行包含两个整数,N (1  < =  N  < =  2M) 和M (1  < =  M  < =  200,000),分别表示星球的
    数目和以太隧道的数目。星球用 0 ~ N-1的整数编号。接下来的M行,每行包括两个整数X, Y,其中(0 < = X <> 
    Y 表示星球x和星球y之间有“以太”隧道,可以直接通讯。接下来的一行为一个整数k,表示将遭受攻击的星球的
    数目。接下来的k行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这k个数互不相同,且都在0到n-1的范
    围内。

    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 <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    const int X = 400005;
    int p[X];
    
    struct node{
        int x,y,next;
    }edge[X*2];
    
    int po[X],tol;
    bool use[X];
    int a[X],tot;
    int vec[X];
    int n,m;
    
    void add(int x,int y)
    {
        edge[++tol].x=x;
        edge[tol].y=y;
        edge[tol].next=po[x];
        po[x]=tol;
    }
    
    int find_set(int x)
    {
        if(x!=p[x])
            p[x]=find_set(p[x]);
        return p[x];
    }
    
    void init()
    {
        memset(po,0,sizeof(po));
        tol=0;
        for(int i=1;i<=n;i++)
        {
            use[i]=true;
            p[i]=i;
        }
        int x,y;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            x++;
            y++;
            add(x,y);
            add(y,x);
        }
        scanf("%d",&tot);
        for(int i=1;i<=tot;i++)
        {
            scanf("%d",&a[i]);
            a[i]++;
            use[a[i]] = false;//先将要删的边标记。 
        }
    }
    
    void solve()
    {
        int x,y,px,py;
        for(int i=1;i<=tol;i+=2)
        {
            x=edge[i].x;
            y=edge[i].y;
            if(use[x]&&use[y])//合并 
            {
                px=find_set(x);
                py=find_set(y);
                p[px]=py;
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)//统计连通分量 
            if(use[i]&&p[i]==i)
                ans++;
        for(int i=tot;i;i--)//倒序 离线 
        {
            vec[i]=ans;
            int x=a[i];
            use[x]=1;//加入一个星球 
            ans++;
            for(int j=po[x];j;j=edge[j].next)//加边统计 
            {
                int y=edge[j].y;
                if(use[y])
                {
                    py=find_set(y);
                    px=find_set(x);
                    if(px!=py)
                    {
                        p[px]=py;
                        ans--;
                    }
                }
            }
        }
        vec[0] = ans;
        for(int i=0;i<=tot;i++)
            printf("%d
    ",vec[i]);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        init();
        solve();
        return 0;
    }
    心若向阳,无言悲伤
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    MS17-010(永恒之蓝)远程溢出漏洞
    SQL注入实战之盲注篇(布尔、时间盲注)
    kali下vulhub的使用
    SQL注入实战之报错注入篇(updatexml extractvalue floor)
    SQL注入实战之联合查询篇(含漏洞网站搭建)
    apache/nginx/IIS日记记录分析
    nvcatmysql的安装
    乌云(wooyun)虚拟机的搭建复活
    Web安全基础笔记
    公告、留言
  • 原文地址:https://www.cnblogs.com/L-Memory/p/6160100.html
Copyright © 2011-2022 走看看