Codeforces Round #599 (Div. 1) B. 0-1 MST 圖論


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 𝑛 vertices. It is a complete graph: each pair of vertices is connected by an edge. The weight of each edge is either 0 or 1; exactly 𝑚 edges have weight 1, and all others have weight 0.

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 𝑛 and 𝑚 (1≤𝑛≤105, 0≤𝑚≤min(𝑛(𝑛−1)2,105)), the number of vertices and the number of edges of weight 1 in the graph.

The 𝑖-th of the next 𝑚 lines contains two integers 𝑎𝑖 and 𝑏𝑖 (1≤𝑎𝑖,𝑏𝑖≤𝑛, 𝑎𝑖≠𝑏𝑖), the endpoints of the 𝑖-th edge of weight 1.

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
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
2
input
3 0
output
0

Note

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

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

題意

現在有n個點的完全圖,其中m條邊的長度是1,其他都是0;問你這個圖的最小生成樹的代價是多少?

題解

考慮一下最小生成樹,實際上在這道題可以理解為0邊的聯通塊一共有多少個,如果有k個,那么答案就是k-1.

然后代碼需要優化一下,我們維護兩個集合,一個集合是當前已經聚合成連痛塊的點,和一堆還在外面沒有討論過的點。

考慮均攤,我們每個點只會訪問一次,每條邊也只會訪問一次,那么復雜度就是(n+m)logn <---- set的復雜度。但這個vis數組的復雜度有點迷,不太會算。。。

代碼

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;
set<int>g[maxn];
set<int>vis;
int u[maxn];
void dfs(int x){
	u[x]=1;
	vis.erase(x);
	vector<int>ret;
	for(int p:vis){
		if(!g[x].count(p)){
			ret.push_back(p);
		}
	}
	for(int t:ret){
		vis.erase(t);
	}
	for(int t:ret){
		u[t]=1;
		dfs(t);
	}
}
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int x,y;
		cin>>x>>y;
		x--,y--;
		g[x].insert(y);
		g[y].insert(x);
	}
	for(int i=0;i<n;i++){
		vis.insert(i);
	}
	int ans = 0;
	for(int i=0;i<n;i++){
		if(!u[i]){
			ans++;
			dfs(i);
		}
	}
	cout<<ans-1<<endl;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM