染色
有 nn 个气球(编号 1∼n1∼n),其中第 ii 个气球的颜色为 cici。
气球一共有 kk 种颜色(编号 1∼k1∼k),每个气球的颜色 cici 都满足 1≤ci≤k1≤ci≤k。
接下来要进行 mm 次询问,每次询问给定两个整数 l,rl,r,并询问第 ll 个气球和第 rr 个气球的颜色是否相同。
我们希望所有询问都能得到肯定的回答(即每次询问的两个气球的颜色都相同)。
为了达成这一目的,我们可以对其中一些气球进行重新染色,被重新染色的气球的颜色也应在 [1,k][1,k] 范围内。
为了节约染料,我们希望重新染色的气球数量尽可能少。
请问,最少需要重新染色多少个气球。
注意,所有染色必须在第一次询问开始之前完成。
输入格式
第一行包含三个整数 n,m,kn,m,k。
第二行包含 nn 个整数 c1,c2,…,cnc1,c2,…,cn。
接下来 mm 行,每行包含两个整数 l,rl,r。
输出格式
一个整数,表示最少需要重新染色的气球数量。
数据范围
前 55 个测试点满足,2≤n≤102≤n≤10,0≤m≤50≤m≤5,1≤k≤51≤k≤5。
所有测试点满足,2≤n≤2×1052≤n≤2×105,0≤m≤2×1050≤m≤2×105,1≤k≤2×1051≤k≤2×105,1≤ci≤k1≤ci≤k,1≤l,r≤n1≤l,r≤n,l≠rl≠r。
输入样例1:
3 2 3
1 2 3
1 2
2 3
输出样例1:
2
输入样例2:
3 2 2
1 1 2
1 2
2 1
输出样例2:
0
思路:把需要颜色一样的划分到一个集合中,求每个集合中颜色最多的球的数量,再用集合中球的总数减去颜色最多的球的数量,即是每个集合需要的最少的重新染色量,最后再每个集合相加即可。
代码如下:
#include<iostream>
#include<vector>
using namespace std;
const int N=200005;
int col[N],f[N],cnt[N];
int n,m,k,ans;
vector<int> s[N];
int find(int x)
{
if(f[x]!=x)f[x]=find(f[x]);
return f[x];
}
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=n;i++)cin>>col[i];
while(m--)
{
int a,b;
cin>>a>>b;
f[find(a)]=find(b);
}
for(int i=1;i<=n;i++)s[find(i)].push_back(i);
for(int i=1;i<=n;i++)
{
if(s[i].size())
{
int t=-1;
for(auto it=s[i].begin();it!=s[i].end();it++)
{
auto x=*it;
cnt[col[x]]++;
t=max(t,cnt[col[x]]);
}
ans+=s[i].size()-t;
//for(auto it=s[i].begin();it!=s[i].end();it++)
//{
// auto x=*it;
// cnt[col[x]]--;
//}
for(auto x:s[i])
{
cnt[col[x]]--;
}
}
}
cout<<ans;
return 0;
}