其他分享
首页 > 其他分享> > [JSOI2008]星球大战

[JSOI2008]星球大战

作者:互联网

题目链接:星球大战

#include<iostream>
#include<vector>
using namespace std;
const int N = 4e5 + 5;
vector<int> g[N];
int brk[N], res[N], par[N], bp[N];
int n, m, k;
int find(int x)
{
    return par[x] == x ? x : par[x] = find(par[x]);
}
void merge(int x, int y)
{
    par[find(x)] = find(y);
}
int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i++) par[i] = i;
    for(int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    cin >> k;
    for(int i = 0; i < k; i++)
    {
        int x;
        cin >> x;
        brk[x] = 1; //标记被炸的星球
        bp[i] = x; //记录第几号星球被破坏
    }
    int cnt = n; //当前连通块个数(假设每个星球都为一个连通块)
    for(int i = 0; i < n; i++)
    {
        if(brk[i]) //若该星球被破坏则连通块数量减一
        {
            cnt --;
            continue;
        }
        for(int j = 0; j < g[i].size(); j++)
        {
            int v = g[i][j];
            if(!brk[v] && find(v) != find(i)) //若星球v没被破坏且与星球i不在一个连通块则将两者进行合并,连通块数量也随之减一
            {
                merge(i, v);
                cnt --;
            }
        }
    }
    res[k] = cnt;
    for(int i = k - 1; i >= 0; i--)
    {
        int v = bp[i];
        brk[v] = 0; //星球v已经修复
        cnt ++; //星球v修复后连通块数量+1
        for(int j = 0; j < g[v].size(); j++)
        {
            int u = g[v][j];
            if(!brk[u] && find(u) != find(v))
            {
                merge(u, v);
                cnt --;
            }
        }
        res[i] = cnt;
    }
    for(int i = 0; i <= k; i++)
        cout << res[i] << endl;
    return 0;
}

标签:连通,星球大战,int,JSOI2008,cnt,brk,星球,find
来源: https://www.cnblogs.com/K2MnO4/p/14623910.html