您的位置:首页 > 其它

CodeForces 731 C.Socks(贪心+并查集)

2017-04-29 11:12 549 查看
Description

m天n只袜子,袜子有k种颜色,每次操作可以将任一只袜子染成这k种颜色的任一种,要求第i天只能穿第li只和第ri只袜子,问最少操作多少次可以使得每一天穿的袜子颜色都相同

Input

第一行三个整数n,m,k分别表示袜子数,天数和颜色数,之后n个整数c[i]表示第i只袜子的颜色,最后m行每天两个整数li和ri表示第i天要穿的两只袜子(2<=n<=2e5,0<=m<=2e5,1<=k<=2e5,1<=c[i]<=k,1<=li!=ri<=n)

Output

输出最少操作数使得每一天穿的袜子颜色都相同

Sample Input

3 2 3

1 2 3

1 2

2 3

Sample Output

2

Solution

把每只袜子看作一个集合,把每一天穿的两只袜子所在集合合并表示一个集合中的袜子颜色需要相同,那么对于每一个集合,选取其中出现次数最多的袜子不变,其他袜子均染成这个颜色可以使得操作数最低,把每个集合要染的袜子数累加即为答案

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 222222
int n,m,k,c[maxn],f[maxn],num[maxn];
vector<int>v[maxn];
map<int,int>M;
map<int,int>::iterator it;
void init(int n)
{
for(int i=1;i<=n;i++)f[i]=i,num[i]=1,v[i].clear();
}
int find(int x)
{
if(f[x]==x)return x;
return f[x]=find(f[x]);
}
void unite(int x,int y)
{
x=find(x),y=find(y);
if(x==y)return ;
f[x]=y,num[y]+=num[x];
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&k))
{
for(int i=1;i<=n;i++)scanf("%d",&c[i]);
init(n);
for(int i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
unite(l,r);
}
int res=0;
for(int i=1;i<=n;i++)
v[find(i)].push_back(c[i]);
int ans=0;
for(int i=1;i<=n;i++)
if(find(i)==i&&v[i].size()>1)
{
M.clear();
for(int j=0;j<v[i].size();j++)
M[v[i][j]]++;
int temp=0;
for(it=M.begin();it!=M.end();it++)
temp=max(temp,it->second);
ans+=v[i].size()-temp;
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: