反向建边的思路,感觉和题解写的差不多啊,但就是过不去

P1197 [JSOI2008] 星球大战

gjh303987897 @ 2021-11-15 20:02:47

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define maxn 500005
using namespace std;
int n,m,k,ans[maxn],vis[maxn],fa[maxn],x[maxn],y[maxn],bui[maxn];
int read(){
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0'){
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
struct data{
    int next,to;
}t[maxn*2+1];
int head[maxn],js;
inline void add(int u,int v){
    t[++js].next=head[u];
    head[u]=js;
    t[js].to=v;
} 
int find(int r){
    if(fa[r]!=r) fa[r]=find(fa[r]);
    return fa[r];
}
void un(int r1,int r2){
    r1=find(r1); r2=find(r2);
    if(r1!=r2) fa[r2]=r1;
}
bool judge(int r1,int r2){
    r1=find(r1); r2=find(r2);
    if(r1!=r2) return false;
    else return true; 
}
int main()
{
    cin>>n>>m;//n=read(); m=read();

    for(int i=1;i<=m;i++){
        x[i]=read(); y[i]=read();
        add(x[i],y[i]); add(y[i],x[i]);
    }
    k=read(); for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=k;i++){
        bui[i]=read(); vis[bui[i]]=1;
    }
    ans[k+1]=n-k;
    for(int i=1;i<=m;i++){
        if(!vis[x[i]]&&!vis[y[i]]&&!judge(x[i],y[i])){
            un(x[i],y[i]); ans[k+1]--; 
        }
    }

    int que=ans[k+1];
    for(int i=k;i>=1;i--){
        vis[bui[i]]=0; que++;
        for(int j=head[bui[i]];j!=0;j=t[j].next){
            if(!vis[t[j].to]&&judge(bui[i],t[j].to)==false){
            un(bui[i],t[j].to); que--; 
            }
        }
        ans[k]=que;
    }
    for(int i=1;i<=k+1;i++){
        cout<<ans[i]<<endl;
    } 
    return 0; 
}

by Wf_yjqd @ 2023-03-04 21:20:32

你知道啥是反向建边么。。


|