bzoj 1015: [JSOI2008]星球大戰starwar 並查集

weixin_34126215發表於2015-06-12

1015: [JSOI2008]星球大戰starwar

Time Limit: 20 Sec

Memory Limit: 256 MB

題目連線

http://www.lydsy.com/JudgeOnline/problem.php?id=1015

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

HINT

 

題意

 

題解:

倒著並查集就好了~

直接搞

程式碼:

 

//qscqesze
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 1000000
#define mod 10007
#define eps 1e-9
int Num;
char CH[20];
//const int inf=0x7fffffff;   //нчоч╢С
const int inf=0x3f3f3f3f;
/*
 
inline void P(int x)
{
    Num=0;if(!x){putchar('0');puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
*/
inline ll read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void P(int x)
{
    Num=0;if(!x){putchar('0');puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
//**************************************************************************************
const int N = 500000, M = 500000;
int key[M], head[N], next[M], cnt;
int a[N], p[N], ans[N];
bool v[N];
inline void add(const int & x, const int & y)
{
    key[cnt] = y;
    next[cnt] = head[x];
    head[x] = cnt ++;
}
inline int F (int x) 
{ 
    return p[x] == x ? x : p[x] = F (p[x]); 
}
int main ()
{
    int n, m;memset (head, -1, sizeof head);
    scanf ("%d%d", &n, &m);
    for (int i = 1, a, b; i <= m; i ++)
        scanf ("%d%d", &a, &b), add (a, b), add (b, a);int k;
    scanf ("%d", &k);
    for (int i = 1; i <= k; i ++)
        scanf ("%d", &a[i]), v[a[i]] = true;
    for (int i = 1; i <= n; i ++)
        p[i] = i;
    int z = n - k;
    for (int i = 0; i < n; i ++)
        if (!v[i])
            for (int j = head[i]; ~ j; j = next[j])
                if (!v[key[j]])
                    if (F (i) != F (key[j]))
                        p[F (i)] = F (key[j]), z --;
    ans[k + 1] = z;
    for (int i = k; i >= 1; i --)
    {
        v[a[i]] = false;    
        z ++;
        for (int j = head[a[i]]; ~ j; j = next[j])
            if (!v[key[j]])
                if (F (a[i]) != F (key[j]))
                    p[F (a[i])] = F (key[j]), z --;
        ans[i] = z;
    }
    for (int i = 1; i <= k + 1; i ++)
        printf ("%d\n", ans[i]);
    return 0;
}

 

相關文章