D. Social Network(并查集修改连通块数量)

Problem - D - Codeforces

 

威廉来到了一个专门讨论加密货币的会议。要想了解加密货币世界的最新消息,建立联系、认识新朋友、利用朋友的关系是必不可少的。

会议有N个参与者,他们最初都不熟悉对方。威廉可以把之前不熟悉的任何两个人a和b介绍给对方。

威廉有d个条件,其中第i个条件要求人xi与人yi有联系。从形式上看,如果有这样一条链p1=x,p2,p3,...,pk=y,对于1到k-1的所有i来说,编号为pi和pi+1的两个人确实认识对方,则两个人有联系。

对于每一个i(1≤i≤d),威廉希望你能计算出一个人能够拥有的最大的熟人数量,假设威廉满足了从1到i(包括i)的所有条件,并且正好进行了i次介绍。这些条件是在威廉进行了i次介绍之后被检查出来的。每个i的答案必须独立计算。这意味着,当你计算i的答案时,你应该假设还没有两个人被介绍给对方。

输入
第一行包含两个整数n和d(2≤n≤103,1≤d≤n-1),分别是人的数量和条件的数量。

接下来的d行各包含两个整数xi和yi (1≤xi,yi≤n,xi≠yi),根据条件i必须有联系的人数。

输出
如果William进行了i次介绍并满足了前i个条件,则第i个数字必须等于拥有最大可能的熟人的人数。

例子
输入复制
7 6
1 2
3 4
2 4
7 6
6 5
1 7
输出拷贝
1
1
3
3
3
6
输入复制
10 8
1 2
2 3
3 4
1 4
6 7
8 9
8 10
1 4
输出拷贝
1
2
3
4
5
5
6
8
备注
对第一个测试案例的解释。

在这个解释中,圆圈和其中的数字表示具有相应数字的人。这条线表示威廉介绍了两个有联系的人。标记为红色的人有最多的熟人。这些并不是介绍人的唯一正确方法。

题解:
我们每次并查集找x,y是否连接

如果未连接,我们就应该让他们连接上,清空其中一个块的数目,加到另一个块上,并且连接他们

如果已经连接.那我们就有额外一次连接机会k++(初始为1),排序找到前k个最大的相加ans

答案为ans - 1

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
using namespace std;
#define int long long
int f[1030];
int siz[1030];
int w[1030];
int find(int x)
{
	if(f[x] == x)
	return x;
	return f[x] = find(f[x]);
}
void solve()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin >> n >>m;
	for(int i = 1;i <= n;i++)
	{
		f[i] = i;
		siz[i] = 1;
	}
	int cnt = 1;
	while(m--)
	{
		int x,y;
		cin >> x >> y;
		if(find(x) == find(y))
		{
			cnt++;
		}
		else
		{
			siz[find(x)] += siz[find(y)];
			siz[find(y)] = 0;
			f[find(y)] = find(x);
		}
		for(int i = 1;i <= n;i++)
		{
			w[i] = siz[i];
		}
		sort(w+1,w+1+n,greater<int>());
		int ans = 0;
		for(int i = 1;i <= cnt;i++)
		{
			ans += w[i];
		}
		cout<<ans-1<<"\n";
	}
}
signed main()
{
	int t = 1;
//	cin >> t;
	while(t--)
	{
		solve();
	}
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值