【并查集】【最大连通块大小】D. Social Network

245 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目链接:
codeforces.com/problemset/…

题意看了好长时间,看不懂,英语太难了😭😭😭

d个条件,到达第i个条件时,要保证前i个条件中的xy是连通的(不是必须相连),且图中需要共有i条边,求最大连通块的大小

也就是说,如果之前的条件已经让xy连通了,这次没必要再连接xy了,可以自由支配连接一条边


对于每次询问xy

最后结果为res-1,除去本身


cnt:代表可以自由连接边的条数
ve[]:代表所有连通块大小的数组,之后会对其进行从大到小排序

对于并查集的模板我们还是有必要知道并且熟练掌握的。并查集是平常出题中非常常见的数据结构,不知道它的话基本很多题目都做不了。并查集主要就是一个查找的函数还有一个合并的函数,两个都对原理理解透彻的话才能在平时的做题中游刃有余。

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int N = 1e5+5;


struct dsu
{
	vector<int>f,sz; 
	dsu(int n)
	{
		f.resize(n);
		sz.resize(n,1);
		for(int i=0;i<n;i++) f[i] = i;
	}		
	void merge(int x,int y)
	{
		x = find(x);
		y = find(y);
		if(x == y) return; 
		if(x > y) swap(x,y);
		f[y] = x;
		sz[x] += sz[y];
		sz[y] = 0;
	}
	int find(int x)
	{
		return f[x]==x ? x : f[x]=find(f[x]);
	}
};

void solve()
{
	int n,m;
	cin>>n>>m;
	dsu tr(n+1);
	int cnt = 0;

	while(m--)	
	{
		int u, v;
		cin>>u>>v;
		int x = tr.find(u);
		int y = tr.find(v);
		if(x == y) cnt ++;
		else tr.merge(x,y);
		
		vector<int> ve;
		for(int i=1;i<=n;i++)
			if(tr.sz[i]) ve.push_back(tr.sz[i]);	
			
		sort(ve.begin(),ve.end(),greater<int>());
		int res = 0;
		for(int i=0;i<=cnt and i<ve.size();i++)
			res += ve[i];
		cout<<res - 1<<endl;
	}
}

int main()
{
	int t;
//	cin>>t;
	t = 1;
	while(t--) solve();
	return 0;
}