当前位置 博文首页 > duanghaha的博客:【codeforces 1243】D. 0-1 MST(补图的连通块

    duanghaha的博客:【codeforces 1243】D. 0-1 MST(补图的连通块

    作者:[db:作者] 时间:2021-09-21 20:56

    题意:

    给你一个图,求补图的连通块个数。

    题解:

    考虑用使用并查集,用set存已经被放入并查集的点,对于没有放入的点,计算该点和联通块相连的点的个数,如果相连的点的个数小于联通块大小,则直接连进去即可。时间复杂度 O ( n + m ? l o g ) O(n+m*log) O(n+m?log)

    代码:

    #include<bits/stdc++.h>
     
    using namespace std;
    const int N = 1e6+100;
    int par[N],siz[N];
    int cnt[N];
    struct edge{
        int u,v,w;
    }e[N];
    vector<int> G[N];
    int find(int x){
        return x==par[x]?x:par[x]=find(par[x]);
    }
    void unite(int x,int y){
        x=find(x);
        y=find(y);
        if(x==y) return ;
        par[x]=y;
        siz[y]+=siz[x];
    }
    int main(){
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        int n,m,u,v;
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            par[i]=i;
            siz[i]=1;
        }
        for(int i=1;i<=m;i++){
            cin>>u>>v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        int ans=n-1;
        set<int> st;
        st.insert(1);
        for(int i=2;i<=n;i++){
            for(int v:G[i]){
                cnt[find(v)]++;//和各联通块相连的点的个数
            }
            for(auto it=st.begin();it!=st.end();){
                int an=find(*it);
                if(cnt[an]<siz[an]){
                    unite(*it,i);
                    st.erase(it++);
                    ans--;
                }else it++;
            }
            for(int v:G[i]) cnt[find(v)]=0;
            st.insert(i);
        }
        cout<<ans<<endl;
        return 0;
    }
    
    cs