zoukankan      html  css  js  c++  java
  • BJOJ1015|星球大战starwar|并查集|离线操作

    Description
    很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系。某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。 但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通快的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)。
    Input
    输入文件第一行包含两个整数,N (1 <= N <= 2M) 和M (1 <= M <= 200,000),分别表示星球的数目和以太隧道的数目。星球用0~N-1的整数编号。接下来的M行,每行包括两个整数X, Y,其中(0<=X<>Y
    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<iostream>
    #include<cstdio>
    using namespace std;

    int fa[400001],use[400001],des[200001],tot=0,cnt=0;

    struct node{
           int from,next,to;
    }e[200001];
    int head[400001],a[400001],ans[400001];

    int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); }

    void insert(int x,int y)
    {
         e[++tot].from=x; e[tot].to=y;
         e[tot].next=head[x]; head[x]=tot;
    }

    void add(int x)
    {
         int i=head[x];
         int q=fa[x];
         while (i)
         {
               if (use[e[i].to])
               {
                                int p=find(e[i].to);
                                if (p!=q) { fa[q]=p; cnt--; }
               }
               i=e[i].next;
         }
    }

    int main()
    {
        int n,m;
        cin >> n >> m;
        for (int i=1; i<=n; i++) fa[i]=i;
        for (int i=1; i<=m; i++)
        {
            int x,y;
            cin >> x >> y;
            insert(x,y); insert(y,x);
        }
        cin >> m;
        for (int i=1; i<=m; i++)
        {
            cin >> a[i];
            des[a[i]]=1;
        }
        for (int i=1; i<=n; i++)
            if (!des[i])
            {
                         cnt++;
                         add(i);
                         use[i]=1;
            }
        ans[m+1]=cnt;
        for (int i=m; i>=1; i--)
        {
            cnt++;
            add(a[i]);
            use[a[i]]=1;
            ans[i]=cnt;
        }
        for (int i=1; i<=m+1; i++) cout << ans[i] << endl;
        system("pause");
        return 0;
    }
  • 相关阅读:
    poj 3616 Milking Time
    poj 3176 Cow Bowling
    poj 2229 Sumsets
    poj 2385 Apple Catching
    poj 3280 Cheapest Palindrome
    hdu 1530 Maximum Clique
    hdu 1102 Constructing Roads
    codeforces 592B The Monster and the Squirrel
    CDOJ 1221 Ancient Go
    hdu 1151 Air Raid(二分图最小路径覆盖)
  • 原文地址:https://www.cnblogs.com/Shymuel/p/4656324.html
Copyright © 2011-2022 走看看