bzoj 1015 [JSOI2008]星球大战starwar

Posted huangchenyan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1015 [JSOI2008]星球大战starwar相关的知识,希望对你有一定的参考价值。

并查集

题目中是说将节点一个个摧毁,正着做并不好做

所以考虑在所有的星球摧毁后反着进行连边

在恢复一个节点后,则恢复了这个节点到之前已恢复的节点的连边,然后用并查集维护联通块即可

注意在同一个联通块中连边是不会改变联通块的个数的

所以只要处理联通块之间的边即可

#include <bits/stdc++.h>
using namespace std;
const int MAXN=4*1e5+100;
int n,m,k,fa[MAXN],q[MAXN],color[MAXN];
int now,nf[MAXN],vi[MAXN];
vector <int> e[MAXN],ans;
int find(int x)//并查集

    if (fa[x]==x)
      return fa[x];
    fa[x]=find(fa[x]);
    return fa[x];

void dfs(int x,int now)

    color[x]=now;
    for (int i=0;i<(int)e[x].size();i++)
    
        if (color[e[x][i]])
          continue;
        dfs(e[x][i],now);
    

int main()

    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    
        int u,v;
        scanf("%d%d",&u,&v);
        e[u].push_back(v);
        e[v].push_back(u);
    
    scanf("%d",&k);
    for (int i=1;i<=k;i++)
    
        scanf("%d",&q[i]);
        vi[q[i]]=1;
    
    int co=0;
    for (int i=0;i<n;i++)
    
        if (color[i])
          continue;
        co++;
        dfs(i,co);
    //对残余的图进行染色,判断联通块
    printf("%d\n",co);
    for (int i=0;i<n;i++)
      fa[i]=i;
    for (int i=0;i<n;i++)
    
        if (vi[i])
          continue;
        for (int j=0;j<(int)e[i].size();j++)
        
            if (vi[e[i][j]])
              continue;
            if (find(e[i][j])!=find(i))
            
                fa[find(i)]=find(e[i][j]);
            
        
    
    for (int i=0;i<n;i++)
    
        if (vi[i])
          continue;
        if (nf[find(i)]==0)
        
            now++;
            nf[find(i)]=1;
        
    
    for (int i=k;i>=1;i--)
    
        ans.push_back(now);
        int u;
        u=q[i];
        vi[u]=0;
        for (int j=0;j<(int)e[u].size();j++)
        
            if (vi[e[u][j]])
              continue;
            int v;
            v=e[u][j];//进行加边
            if (find(u)!=find(v))
            
                if (nf[find(u)]==1 && nf[find(v)]==1)
                
                    nf[find(u)]=0;
                    now--;
                
                fa[find(u)]=find(v);
            
        
        if (nf[find(u)]==0)
        
            nf[find(u)]=1;
            now++;
        
    
    for (int i=(int)ans.size()-1;i>=0;i--)
      printf("%d\n",ans[i]);

 

以上是关于bzoj 1015 [JSOI2008]星球大战starwar的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1015 [JSOI2008]星球大战starwar

bzoj 1015: [JSOI2008]星球大战starwar

BZOJ1015[JSOI2008]星球大战starwar[并查集]

BZOJ-1015: [JSOI2008]星球大战starwar (并查集)

bzoj1015 [JSOI2008]星球大战starwar

bzoj 1015: [JSOI2008]星球大战starwar