Codeforces 731C:Socks(并查集)
http://codeforces.com/problemset/problem/731/C
题意:有n只袜子,m天,k个颜色,每个袜子有一个颜色,再给出m天,每天有两只袜子,每只袜子可能不同颜色,问要让每天的袜子是相同颜色的,要重新染色的袜子数最少是多少。
思路:并查集合并,将同一天的袜子合并起来,然后就形成了cnt个集合,每个集合都是独立的,因此排序,找出每个集合里面袜子颜色相同的最多的是哪个颜色,然后把其他不属于这个颜色的都染成这个颜色,那么这样重新染色的袜子数是最少的。然后每个集合的答案加起来就是最后的结果了。还怕这样太暴力会超时,还好没有。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 #include <map> 10 #include <set> 11 using namespace std; 12 #define INF 0x3f3f3f3f 13 #define N 200010 14 typedef long long LL; 15 int fa[N], col[N], root[N], vis[N]; 16 vector<int> vec[N]; 17 18 int Find(int x) { 19 if(x == fa[x]) return x; 20 return fa[x] = Find(fa[x]); 21 } 22 23 void Merge(int x, int y) { 24 x = Find(x), y = Find(y); 25 if(x == y) return ; 26 fa[x] = y; 27 } 28 29 int main() { 30 int n, m, k; 31 cin >> n >> m >> k; 32 for(int i = 1; i <= n; i++) { 33 fa[i] = i; 34 scanf("%d", &col[i]); 35 } 36 for(int i = 0; i < m; i++) { 37 int u, v; 38 scanf("%d%d", &u, &v); 39 vis[u] = vis[v] = 1; 40 Merge(u, v); 41 } 42 int cnt = 0; 43 for(int i = 1; i <= n; i++) { 44 if(vis[i]) { 45 if(fa[i] == i) root[++cnt] = i; 46 vec[Find(i)].push_back(col[i]); 47 } 48 } 49 int ans = 0; 50 for(int i = 1; i <= cnt; i++) 51 sort(vec[root[i]].begin(), vec[root[i]].end()); 52 for(int i = 1; i <= cnt; i++) { 53 int now = 1, ma = 0; 54 for(int j = 1; j < vec[root[i]].size(); j++) { 55 if(vec[root[i]][j] != vec[root[i]][j-1]) { 56 ma = max(ma, now); now = 1; 57 } else now++; 58 } 59 ma = max(now, ma); 60 ans += vec[root[i]].size() - ma; 61 } 62 printf("%d\n", ans); 63 return 0; 64 }