CodeForces 731C C - Socks 并查集

题目链接:点击打开链接

题目大意:n只袜子,并对袜子标号为1-n。然后用k种颜色对n只袜子染色.

接下来给出m天要用的袜子(每天2只),要求这使这m天,每天两只袜子的颜色相同,问至少需要染几只袜子。

思路就是:


首先用并查集,将他们分组,同一天的袜子最后要求颜色相同,所以将他们分入同一个并查集。

然后用vector数组存储每个并查集,要求同一个并查集中的袜子要是相同的颜色。那么本来有2号颜色是最多的话。那么其它都要变成2号颜色。

即通过一个数组对并查集内的每种颜色的袜子进行统计,那么对于每个并查集需要变化的袜子数等于并查集总的袜子数量减去某个颜色最多的袜子数量,即除了袜子数量最多的颜色,其他颜色的袜子都需要变成这个颜色。

这里我们注意下都对这个统计颜色数量的数组清零的操作,不能用memset,会超时,改变了哪个颜色,最后就把他清0即可。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn=200100;
int pre[maxn];
int n,m,k;
int color[maxn];
vector<int>v[maxn];
int num[maxn];
int init()
{
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&color[i]);
		pre[i]=i;
	}
	memset(num,0,sizeof num);
}
int fid(int x)
{
	int r=x;
	while(pre[r]!=r)
		r=pre[r];
	int i=x,j;
	while(i!=r)
	{
		j=pre[i];
		pre[i]=r;
		i=j;
	}
	return r;
}
void join(int x,int y)
{
	int fx=fid(x),fy=fid(y);
	if(fx!=fy)
	{
		pre[fx]=fy;
	}
}
int main(void)
{
	int a,b;
	while(~scanf("%d%d%d",&n,&m,&k))
	{
		init();
		for(int i=0;i<m;i++)
		{
			scanf("%d%d",&a,&b);
			join(a,b);
		}
		for(int i=1;i<=n;i++)
		{
			v[fid(i)].push_back(i);//将每个元素加入到相应的并查集中去
		}
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			if(v[i].size()==0)continue;
			//memset(num,0,sizeof num);
			int maxe=-1;
			for(int j=0;j<v[i].size();j++)
			{
				num[color[v[i][j]]]++;
			}

			for(int j=0;j<v[i].size();j++)
			{
				maxe=max(maxe,num[color[v[i][j]]]);
				num[color[v[i][j]]]=0;
			}

		//	cout<<v[i].size()<<endl;
			ans+=v[i].size()-maxe;

		}
		printf("%d\n",ans);
	}
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值