【codeforces 1243】D. 0-1 MST(補圖的連通塊計數)

題意:

給你一個圖,求補圖的連通塊個數。

題解:

考慮用使用並查集,用set存已經被放入並查集的點,對於沒有放入的點,計算該點和聯通塊相連的點的個數,如果相連的點的個數小於聯通塊大小,則直接連進去即可。時間複雜度O(n+mlog)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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章