BZOJ 1015 星球大战starwar

我存图用的邻接表,总觉得应该有更好的方法,无奈智商不够想不出来。

闲话少说,说一说我的步骤:(整体思路,离线、并查集)

    1.存图(邻接表),初始cnt为目前的连通块个数 n-k(当问题以外的点之间没有边,即他们每个点都是一个连通块),用que数组存第i个问题的点,用vis数组记录此点是第几个问题;

    2.先把问题里没有出现的点之间的边加进图中,更新cnt;

    3.从最后一个问题开始倒着循环,ans[i]表示未加入此时删除的点的连通块个数。把每个点关联的边加入图中,并判断如果这条边另一端的点j没有被删除(即vis[j]==0 || vis[i]<vis[j]),如果为真,更新cnt(cnt--),但由于连通快减少的个数总比满足条件的加入的边的个数少1,所以每次cnt还要加1;

    4.激动人心的时刻就要到了:输出ans数组,AC!


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#define MAXN 200010
using namespace std;
struct edge{
    int to;
    edge * p;
} *ed[2*MAXN];
int que[MAXN*2];
int ans[MAXN*2];
int f[MAXN*2];
int vis[MAXN*2];
void add(int a,int b){
    edge * point=new edge;
    point->to=b;
    point->p=ed[a];
    ed[a]=point;
}
int getf(int x){
    return f[x]==x ? x : f[x]=getf(f[x]);
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    int k;
    memset(vis,0,sizeof(vis));
    scanf("%d",&k);
    for(int i=1;i<=k;i++){
        scanf("%d",&que[i]);
        vis[que[i]]=i;
    }
    int cnt=n-k;
    for(int i=0;i<n;i++) f[i]=i;
    for(int i=0;i<n;i++)
        if(!vis[i])
        for(edge* j=ed[i];j;j=j->p){
            if(!vis[j->to] && getf(i)!=getf(j->to)){
                f[getf(j->to)]=getf(i);
                cnt--;
            }
        }   
    for(int i=k;i>=1;i--){
        ans[i]=cnt;
        for(edge* j=ed[que[i]];j;j=j->p){
            int now=j->to;
            if(getf(now)!=getf(que[i]) && (!vis[now] || vis[now]>vis[que[i]])){
                f[getf(now)]=getf(que[i]);
                cnt--;
            }
        }
        cnt++;
    }
    ans[0]=cnt;
    for(int i=0;i<=k;i++) printf("%d\n",ans[i]);
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值