BF的資料結構題單-提高組 ——P1197 [JSOI2008]星球大戰

行走天涯的豆沙包發表於2020-11-11

P1197 [JSOI2008]星球大戰

題解:

經典題,反向加邊。

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
vector<int> g[N];
int pre[N];
typedef pair<int,int> pp;
vector<pp> edge;
int res[N],cnt,vis[N],a[N];
int find(int a)
{
    if(pre[a]!=a) return pre[a]=find(pre[a]);
    return pre[a];
}
void merge(int a,int b)
{
    pre[a]=b;
}
signed main()
{
//    memset(head,-1,sizeof head);
    int n,m; cin>>n>>m;
    int num=n;
    for(int i=0;i<n;i++) pre[i]=i;
    for(int i=1;i<=m;i++){
        int a,b; scanf("%d%d",&a,&b);
        edge.push_back({a,b});
        g[a].push_back(b);
        g[b].push_back(a);
    }
    int k; cin>>k;
    for(int i=1;i<=k;i++){
        int tmp; scanf("%d",&tmp);
        a[i]=tmp;
        vis[tmp]=1;
    }
    int tot=0;
    for(int i=0;i<edge.size();i++){
        if(vis[edge[i].second]||vis[edge[i].first]) continue;
        int fx=find(edge[i].first),fy=find(edge[i].second);
        if(fx==fy) continue;
        merge(fx,fy);
        n--;
        tot++;
    }
//    cout<<"n : "<<n<<endl;
    res[k+1]=num-k-tot;
    for(int i=k;i>=1;i--){
        vis[a[i]]=0;
        for(int j=0;j<g[a[i]].size();j++){
            if(vis[g[a[i]][j]]) continue;
            int fx=find(g[a[i]][j]),fy=find(a[i]);
            if(fx!=fy) {
                merge(fx, fy);
                tot++;
            }
        }
        res[i]=num-i+1-tot;
    }
    for(int i=1;i<=k+1;i++) printf("%d\n",res[i]);
    return 0;
}

相關文章