【BZOJ 1015】 [JSOI2008]星球大战starwar

【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1015

【题意】

【题解】

/*
    可以倒过来考虑;
    相当于一个加入了一个节点;
    然后问你联通块的数量;
    可以记录所有节点有哪些边和它是连在一起的;
    然后查询新加入的节点的边的另外一端是哪些节点;
    之后的操作会让这些节点连起来;
    看看边的另外一端的点对应的不同联通块有多少个->x;
    有多少个联通块就减去x-1;
    (具体实现的时候,先让这个新加入的节点和相邻的点尝试连起来,如果
    它们之前是不连通的那么计数器num递增,然后联通块的个数now=now+1-num);
    用并查集吧。
    (一开始联通块的个数为n-k哦)
*/


【完整代码】

#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
using namespace std;
#define rei(x) scanf("%d",&x)
#define rep2(i,y,x) for (int i = y;i >= x;i--)
#define rep1(i,x,y) for (int i = x;i <= y;i++)

const int N = 4e5 + 1000;
const int M = 2e5 + 1000;

struct abc
{
    int x, y;
};

int n, m,ans[N],now;
int f[N],k,a[N];
bool bo[N];
vector <int> g[N];
abc bian[M];

int ff(int x)
{
    if (f[x] == x) return x;
    else
        return f[x] = ff(f[x]);
}

int main()
{
    //freopen("D:\rush.txt", "r", stdin);
    //freopen("D:\rush_out.txt", "w", stdout);
    rei(n),rei(m);
    rep1(i, 1, m)
    {
        int x, y;
        rei(x), rei(y);
        g[x].push_back(y),g[y].push_back(x);
        bian[i].x = x, bian[i].y = y;
    }
    memset(bo, true, sizeof bo);
    rei(k);
    rep1(i, 1, k)
    {
        rei(a[i]);
        bo[a[i]] = false;
    }
    rep1(i, 0, n-1)
        f[i] = i;
    now = n-k;
    rep1(i, 1, m)
    {
        int x, y;
        x = bian[i].x, y = bian[i].y;
        if (!bo[x] || !bo[y]) continue;
        int r1 = ff(x), r2 = ff(y);
        if (r1 != r2)
        {
            f[r1] = r2;
            now--;
        }
    }
    rep2(i, k, 1)
    {
        ans[i] = now;
        int x = a[i],num = 0;
        bo[x] = true;
        int len = g[x].size();
        now++;
        rep1(j, 0, len - 1)
        {
            int y = g[x][j];
            if (!bo[y]) continue;
            int r1 = ff(y),r2 = ff(x);
            if (r1 != r2)
            {
                f[r1] = r2;
                num++;
            }
        }
        now -= num;
    }
    ans[0] = now;
    rep1(i, 0, k)
        printf("%d
", ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626584.html