题解:CF2060E Graph Composition

题意:给两个图 $F$ 和 $G$,在 $F$ 中删边或加边,使两图连通性相同。

Solution

很容易想到使用并查集来维护连通性和加边,但是要删边的话,会影响整个 $father$ 数组中有关联的点,复杂度不能通过此题。
所以我们反过来想,先在 $F$ 里加边,然后再算多出来的边。

Solving

码风良好。

具体过程见注释。

#include<bits/stdc++.h>
using namespace std;
using LL=long long;
LL t,n,m1,m2,ans,a[500005],b[500005],fag[500005],faf[500005],hg[500005],hf[500005],cnt1,cnt2;
LL findf(LL x){
    if(faf[x]==x) return x;
    return faf[x]=findf(faf[x]);
}
LL findg(LL x){
    if(fag[x]==x) return x;
    return fag[x]=findg(fag[x]);
}
int main(){
    cin>>t;
    while(t--){
        cin>>n>>m1>>m2;
        ans=cnt1=cnt2=0;
        for(int i=1;i<=n;i++){
            faf[i]=fag[i]=i;
            hf[i]=hg[i]=0;
        }
        for(int i=1;i<=m1;i++){
            cin>>a[i]>>b[i];
        }
        for(int x,y,i=1;i<=m2;i++){
            cin>>x>>y;
            fag[findg(x)]=findg(y);//建立并查集
        }
        for(int i=1;i<=n;i++){
            if(!hg[findg(i)]){
                hg[findg(i)]=1,cnt1++; 处理标记
            }
        }
        for(int i=1;i<=m1;i++){
            if(fag[a[i]]==fag[b[i]]){
                faf[findf(a[i])]=findf(b[i]); //需要加的边
            }else ans++;
        }
        for(int i=1;i<=n;i++){
            if(!hf[findf(i)]){
                hf[findf(i)]=1; //需要删的边
                cnt2++;
            }
        }
        cout<<ans+cnt2-cnt1<<endl; //本来就有的边不需要操作
    }
    return 0;
}