洛谷 P1197 星球大战 题解

题面

并查集处理问题的基本思路:如果不是强制在线那么可以倒着处理,把删边改为可爱的加边,然后使用并查集来判断是否联通;

所以可以较为轻松的写出AC代码:

#include <bits/stdc++.h>
using namespace std;
int n,m;
int f[1000010];
struct littlestar{
    int to;
    int nxt;
}star[2000010];
int head[2000010],cnt;
inline void add(int u,int v)
{
    star[++cnt].to=v;
    star[cnt].nxt=head[u];
    head[u]=cnt;
}
int ask[1000010];
inline int zhaobaba(int x)
{
    if(f[x]==x){
        return x;
    }
    return f[x]=zhaobaba(f[x]);
}
int bo[1000010];
int vis[1000010];
int lala[1000010];
int main()
{
    cin>>n>>m;
    for(register int i=1;i<=n;i++){
        f[i]=i;
    }
    for(register int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    int k;
    cin>>k;
    for(register int i=1;i<=k;i++){
        scanf("%d",&ask[i]);
        bo[ask[i]]=1;
    }
    int ans=n-k;
    for(register int u=1;u<=n;u++){
        if(bo[u]) continue;
        else{
            for(register int i=head[u];i;i=star[i].nxt){
                int v=star[i].to;
                if(bo[v]) continue;
                int fx=zhaobaba(u);
                int fy=zhaobaba(v);
                if(fx!=fy){
                    f[fy]=fx;
                    --ans;
                }
            }
        }
    }
    for(register int u=k;u>=1;u--){
        lala[u+1]=ans;
        ++ans;
        bo[ask[u]]=0;
        for(register int i=head[ask[u]];i;i=star[i].nxt){
            int v=star[i].to;
            if(bo[v]) continue;
            int fx=zhaobaba(ask[u]);
            int fy=zhaobaba(v);
            if(fx!=fy){
                f[fy]=fx;
                if(!vis[fy]){
                    --ans;
                    vis[fy]=1;
                }
            }        
        }
    }
    lala[1]=ans;
    for(register int i=1;i<=k+1;i++){
        printf("%d
",lala[i]);
    }
}
原文地址:https://www.cnblogs.com/kamimxr/p/11429922.html