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;
}

猜你喜欢

转载自www.cnblogs.com/Shallow-dream/p/11853785.html