知识点:连通块
这个题首先要看出是图论的模型,因为a和b在一起,b和c在一起,那么想让所有的天数脚上的袜子都一样,那么这三个袜子的颜色都要是一样的,那么就很简单了,袜子就是结点,两脚穿的袜子就是一条无向边,这种连通性的问题用深搜和并查集都可以的,选择使用了深搜,最后的答案就是每个连通块累加,每个连通块的答案就是这个连通块的大小,减去,这个连通块里面出现次数最多的颜色的出现次数,这样这个题就解决了
一开始因为代码问题没有使用并查集,后面去学习了一下并查集的写法,主要是每个连通块统计完答案之后现场还原的问题,后面看了别人代码发现遍历两次就行了,也不是死脑筋非要遍历一次就行的,也不是遇到这种情况都用memset,这样会浪费很多时间
还有,这个题是因为是并查集的练习题才看出了里面的图论模型,这个如果没有这个提示,很有可能看不出来
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int tot, ver[N * 2], nxt[N * 2], head[N];
int a[N], vis[N], cnt;
map<int, int> mp;
void add(int x, int y) {
ver[++tot] = y;
nxt[tot] = head[x]; head[x] = tot;
}
void dfs(int x) {
vis[x] = 1;
cnt++;
mp[a[x]]++;
for (int i = head[x]; i; i = nxt[i]) {
int y = ver[i];
if (!vis[y]) dfs(y);
}
}
int main() {
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
}
while (m--) {
int x, y;
scanf("%d%d", &x, &y);
add(x, y); add(y, x);
}
int ans = 0;
for (int i = 1; i <= n; i++) {
if (!vis[i]) {
mp.clear();
cnt = 0;
dfs(i);
int Max = 0;
for (auto it = mp.begin(); it != mp.end(); it++) {
if (it->second > Max) Max = it->second;
}
ans += cnt - Max;
}
}
cout << ans;
return 0;
}