【并查集+贪心】 CodeForces - 731C - Socks
【题目链接】http://codeforces.com/problemset/problem/731/C
题目大意
输入第一行一个zz有n只袜子,要在接下来的m天穿,袜子有k种颜色
第二行是n只袜子的颜色
接下来m行是每天穿的两只袜子的编号
输出至少要改变几只袜子的颜色才能使这个zz不会因为穿了两只不同颜色的袜子而被嘲笑
解题思路
把袜子作为结点,两只同一天穿的袜子连起来,则改变颜色后每个连通图上的袜子颜色要一样。
第一步:并查集找出连通图
第二步:把袜子的颜色存在它的祖先的vector里
第三步:遍历所有大于1的vector,用map找出颜色最多的,剩下的都要改变颜色
AC代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
const int maxn=200007;
int a[maxn];
vector <int> v[maxn];
int father[maxn];
int find_father(int x)
{
if(x==father[x])
return x;
return father[x]=find_father(father[x]);
}
void join(int x,int y)
{
int fx=find_father(x),fy=find_father(y);
if(fx!=fy)
{
father[fy]=fx;
}
}
int main()
{
int n,m,k,i,j,x,y,ans=0;
scanf("%d%d%d",&n,&m,&k);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
father[i]=i;
}
for(i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
join(x,y);
}
for(i=1;i<=n;i++)
{
v[find_father(i)].push_back(a[i]);
}
ans=0;
int mmax=0;
for(i=1;i<=n;i++)
{
if(v[i].size()>1)
{
mmax=0;
map <int,int> m;
for(j=0;j<v[i].size();j++)
{
//printf("v[%d][%d]=%d ",i,j,v[i][j]);
m[v[i][j]]++;
if(mmax<m[v[i][j]]) mmax=m[v[i][j]];
}
ans+=v[i].size()-mmax;
}
}
printf("%d\n",ans);
return 0;
}