[CodeForces#376 C Socks] 并查集

[CodeForces#376 C Socks] 并查集

题目链接[CodeForces#376 C Socks]
题意描述
Arseniy 有 N 双袜子,然后每双袜子都有一个初始颜色,第i个袜子的颜色记为 ci ,编号为 1 ~N,有 M 天,Arseniy第i天穿指定的两双袜子,编号为 li ri ,要求每双袜子的颜色都必须相同,如果不同,你可以将这个袜子染色染成相同的颜色。问最少染色多少只袜子。PS:读题读了好久…
解题思路
首先,用并查集求出联通块。那么我们开始考虑一个联通块中的所有顶点的最少染色次数。显然, ,这种做法肯定是最少染色次数,不难证明的。
接下来,就是在联通块中统计求答案就好了。

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 200000 + 5;

int N, M, K, C[MAXN];
int fa[MAXN];
int belong[MAXN], tid;
vector<int> G[MAXN];

int Find(int x) { return fa[x] == -1 ? x : fa[x] = Find(fa[x]); }
void Union(int a, int b) {
    a = Find(a), b = Find(b);
    if(a != b) fa[b] = a;
}

int main() {
    int u, v;
    scanf("%d %d %d", &N, &M, &K);
    for(int i = 1; i <= N; i++) scanf("%d", &C[i]), fa[i] = i;
    memset(fa, -1, sizeof(fa));
    for(int i = 1; i <= M; i++) {
        scanf("%d %d", &u, &v);
        Union(u, v);
    }
    tid = 0;
    // 利用belong数组,O(1)离散化
    memset(belong, -1, sizeof(belong));
    for(int i = 1; i <= N; i++) {
        if(belong[Find(i)] == -1) belong[Find(i)] = tid ++;
    }
    for(int i = 0; i < tid; i++) G[i].clear();
    for(int i = 1; i <= N; i++) {
        int id = belong[Find(i)];
        G[id].push_back(i);
    }
    int Ans = 0;
    for(int k = 0; k < tid; k++) {
        int GSZ = G[k].size(), Max = 0;
        /// 这里用cnt数组会TLE,因为数组太大,memset大数组耗时较长
        map<int, int> cnt;
        for(int i = 0; i < GSZ; i++) {
            int& color = C[G[k][i]];
            Max = max(Max, ++cnt[color]);
        }
        Ans += GSZ - Max;
    }
    printf("%d\n", Ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值