• Codeforces Round #599 (Div. 2) D. 0-1 MST (补图连通块计数)


     

    Ujan has a lot of useless stuff in his drawers, a considerable part of which are his math notebooks: it is time to sort them out. This time he found an old dusty graph theory notebook with a description of a graph.

    It is an undirected weighted graph on nn vertices. It is a complete graph: each pair of vertices is connected by an edge. The weight of each edge is either 00 or 11; exactly mm edges have weight 11, and all others have weight 00.

    Since Ujan doesn't really want to organize his notes, he decided to find the weight of the minimum spanning tree of the graph. (The weight of a spanning tree is the sum of all its edges.) Can you find the answer for Ujan so he stops procrastinating?

    Input

    The first line of the input contains two integers nn and mm (1n1051≤n≤105, 0mmin(n(n1)2,105)0≤m≤min(n(n−1)2,105)), the number of vertices and the number of edges of weight 11 in the graph.

    The ii-th of the next mm lines contains two integers aiai and bibi (1ai,bin1≤ai,bi≤n, aibiai≠bi), the endpoints of the ii-th edge of weight 11.

    It is guaranteed that no edge appears twice in the input.

    Output

    Output a single integer, the weight of the minimum spanning tree of the graph.

    Examples
    input
    Copy
    6 11
    1 3
    1 4
    1 5
    1 6
    2 3
    2 4
    2 5
    2 6
    3 4
    3 5
    3 6
    
    output
    Copy
    2
    
    input
    Copy
    3 0
    
    output
    Copy
    0
    
    Note

    The graph from the first sample is shown below. Dashed edges have weight 00, other edges have weight 11. One of the minimum spanning trees is highlighted in orange and has total weight 22.

    In the second sample, all edges have weight 00 so any spanning tree has total weight 00.

     

     

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <cstdlib>
    #include <map>
    #include <vector>
    #include <set>
    #include <queue>
    #include <stack>
    #include <cmath>
    using namespace std;
    #define mem(s,t) memset(s,t,sizeof(s))
    #define pq priority_queue
    #define pb push_back
    #define fi first
    #define se second
    #define ac return 0;
    #define ll long long
    #define cin2(a,n,m)     for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
    #define rep_(n,m)  for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
    #define rep(n) for(int i=1;i<=n;i++)
    #define test(xxx) cout<<"  Test  " <<" "<<xxx<<endl;
    #define TLE std::ios::sync_with_stdio(false);   cin.tie(NULL);   cout.tie(NULL);   cout.precision(10);
    #define lc now<<1
    #define rc now<<1|1
    #define ls now<<1,l,mid
    #define rs now<<1|1,mid+1,r
    #define half no[now].l+((no[now].r-no[now].l)>>1)
    #define ll long long
    #define inf 0x3f3f3f3f
    #define mod 1000000007
    const int mxn = 1e5+10;
    int n,m,k,ans,col,t,flag,vis[mxn];
    ll dp[mxn],pro[mxn];
    string str,ch ;
    map<char,int>mp;
    set<int>st,G[mxn];
    pair <int,int> pa[mxn];
    bool cmp(pair<int,int>x,pair<int,int>y)
    {
        return x.first>y.first;
    }
    void BFS(int x)
    {
        queue<int>q;
        q.push(x);
        st.erase(x);
        while(q.size())
        {
            int now = q.front();
            q.pop();
            if(vis[now])
                continue;
            vis[now] = 1 ;
            for(set<int>::iterator it=st.begin(); it!=st.end();)
            {
                int cnt = *it;
                it++;//set和vector这些容器不能边修改边遍历,需要在修改之前将迭代器往后加一
                if(G[now].find(cnt)==G[now].end())
                {
                    q.push(cnt);
                    st.erase(cnt);
                }
            }
        }
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1; i<=n; i++)
            st.insert(i);
        for(int i=1; i<=m; i++)
        {
            cin>>col>>ans;
            G[col].insert(ans);
            G[ans].insert(col);
        }
        ans = 0;
        for(int i=1; i<=n; i++)
        {
            if(!vis[i])
            {
                BFS(i);
                ans++;
            }
        }
        cout<<ans-1<<endl;
        return 0;
    }

     

    //聚聚:并查集,用set存已经被放入并查集的点,对于没有放入的点,计算该点和联通块相连的点的个数,如果相连的点的个数小于联通块大小,则直接连进去即可。时间复杂度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;
    }
    所遇皆星河
  • 相关阅读:
    SVG
    颜色的小纠结
    Tomcat 安装与配置
    编译java代码出现 错误: 需要class, interface或enum 提示
    Java 开发环境配置
    关于shortcut icon和icon
    转载文章CSS3的calc()使用
    小tip:CSS vw让overflow:auto页面滚动条出现时不跳动——张鑫旭
    CSS计数器(序列数字字符自动递增)详解———张鑫旭
    一起来看看JavaScript中==和===有何不同
  • 原文地址:https://www.cnblogs.com/Shallow-dream/p/11853785.html
Copyright © 2020-2023  润新知