Codeforces 731C:Socks(并查集)

时间:2023-03-09 03:04:46
Codeforces 731C:Socks(并查集)

http://codeforces.com/problemset/problem/731/C

题意:有n只袜子,m天,k个颜色,每个袜子有一个颜色,再给出m天,每天有两只袜子,每只袜子可能不同颜色,问要让每天的袜子是相同颜色的,要重新染色的袜子数最少是多少。

思路:并查集合并,将同一天的袜子合并起来,然后就形成了cnt个集合,每个集合都是独立的,因此排序,找出每个集合里面袜子颜色相同的最多的是哪个颜色,然后把其他不属于这个颜色的都染成这个颜色,那么这样重新染色的袜子数是最少的。然后每个集合的答案加起来就是最后的结果了。还怕这样太暴力会超时,还好没有。

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
typedef long long LL;
int fa[N], col[N], root[N], vis[N];
vector<int> vec[N]; int Find(int x) {
if(x == fa[x]) return x;
return fa[x] = Find(fa[x]);
} void Merge(int x, int y) {
x = Find(x), y = Find(y);
if(x == y) return ;
fa[x] = y;
} int main() {
int n, m, k;
cin >> n >> m >> k;
for(int i = ; i <= n; i++) {
fa[i] = i;
scanf("%d", &col[i]);
}
for(int i = ; i < m; i++) {
int u, v;
scanf("%d%d", &u, &v);
vis[u] = vis[v] = ;
Merge(u, v);
}
int cnt = ;
for(int i = ; i <= n; i++) {
if(vis[i]) {
if(fa[i] == i) root[++cnt] = i;
vec[Find(i)].push_back(col[i]);
}
}
int ans = ;
for(int i = ; i <= cnt; i++)
sort(vec[root[i]].begin(), vec[root[i]].end());
for(int i = ; i <= cnt; i++) {
int now = , ma = ;
for(int j = ; j < vec[root[i]].size(); j++) {
if(vec[root[i]][j] != vec[root[i]][j-]) {
ma = max(ma, now); now = ;
} else now++;
}
ma = max(now, ma);
ans += vec[root[i]].size() - ma;
}
printf("%d\n", ans);
return ;
}