警钟敲烂!!!

P1197 [JSOI2008] 星球大战

You_Quiet @ 2022-11-12 09:10:22

如果在合并函数里进行联通块数量的改动,一定要判断,在处理最后联通块个数时不要改值, (希望你能看懂吧)

rt

正确代码:

void he(int x,int y,bool op){
    int root_x=find(x);
    int root_y=find(y);
    if(root_x!=root_y){
        if(op==1&&v[root_y]!=1&&v[root_x]!=1) root--;
        v[root_x]=0;
        v[root_y]=0;
        if(root_x>root_y) swap(root_x,root_y);
        f[root_y]=root_x;
    }
}

错误代码:

void he(int x,int yp){
    int root_x=find(x);
    int root_y=find(y);
    if(root_x!=root_y){
        if(v[root_y]!=1&&v[root_x]!=1) root--;
        v[root_x]=0;
        v[root_y]=0;
        if(root_x>root_y) swap(root_x,root_y);
        f[root_y]=root_x;
    }
}

最开始的加边

for(int i=1;i<=m;i++){
        if(v[edge[i].from]==0&&v[edge[i].to]==0) {
            he(edge[i].from,edge[i].to,0);
        }
    }
    for(int i=0;i<=n-1;i++){
        int r=find(i);
        if(v1[r]==0&&v[r]==0){
            v1[r]=1;
            root++;
        }
    }

反向加点时的操作

for(int i=k;i>=1;i--){
        root++;
        int Next=a[i];
        int flag=0;
        v[Next]=0;
        for(int o=0;o<bian[Next].size();o++){
            int N=bian[Next][o];
            if(have[N]==1){
                if(v[N]==1) root++;
                v[N]=0;
                he(Next,N,1);
            } 
        }
        have[Next]=1;
        ans[i-1]=root;
    }

但愿你能理解我什么意思吧

可能只有我犯这种很low的错误


|