Loading

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 }

 

posted @ 2017-01-03 23:29  Shadowdsp  阅读(598)  评论(0编辑  收藏  举报