4075 染色(并查集)

1. 问题描述:

有 n 个气球(编号 1∼n),其中第 i 个气球的颜色为 ci。气球一共有 k 种颜色(编号 1∼k),每个气球的颜色 ci 都满足 1 ≤ ci ≤ k。接下来要进行 m 次询问,每次询问给定两个整数 l,r,并询问第 l 个气球和第 r 个气球的颜色是否相同。我们希望所有询问都能得到肯定的回答(即每次询问的两个气球的颜色都相同)。为了达成这一目的,我们可以对其中一些气球进行重新染色,被重新染色的气球的颜色也应在 [1,k] 范围内。为了节约染料,我们希望重新染色的气球数量尽可能少。请问,最少需要重新染色多少个气球。注意,所有染色必须在第一次询问开始之前完成。

输入格式

第一行包含三个整数 n,m,k。第二行包含 n 个整数 c1,c2,…,cn。接下来 m 行,每行包含两个整数 l,r。

输出格式

一个整数,表示最少需要重新染色的气球数量。

数据范围

前 5 个测试点满足,2 ≤ n ≤ 10,0 ≤ m ≤ 5,1 ≤ k ≤ 5。
所有测试点满足,2 ≤ n ≤ 2 × 10 ^ 5,0 ≤ m ≤ 2 × 10 ^ 5,1 ≤ k ≤ 2 × 10 ^ 5,1 ≤ ci ≤ k,1 ≤ l,r ≤ n,l ≠ r。

输入样例1:

3 2 3
1 2 3
1 2
2 3

输出样例1:

2

输入样例2:

3 2 2
1 1 2
1 2
2 1

输出样例2:

0
来源:https://www.acwing.com/problem/content/description/4078/

2. 思路分析:

因为对于每个询问要求最终的颜色是一样的所以我们需要将这两种球的编号放在一个集合中(例如1,2和2,3要求颜色是一样的那么最终1,2,3颜色最终是一样的),这样最终一定会形成若干个集合,每一个集合中的颜色最终是一样的,集合与集合之间的颜色互不干扰,因为涉及到合并元素到集合中的操作,所以我们可以使用并查集合并元素到一个集合中,对于每一个询问使用并查集的查找与合并元素的操作将元素合并到一个集合中,然后枚举编号为1~n的所有气球,通过并查集的find操作将当前气球的编号添加到所在的集合中,这样就会形成若干个集合,因为需要使得重新染色的气球数量最少,所以我们需要统计出每一个集合中出现颜色最多的次数,将其余的气球染成这种颜色那么最终所需要染色的气球数量一定最少的,因为每一个集合的颜色都是相互独立的所以最终加上每一个集合中需要染色的数量就是答案。

3. 代码如下:

from typing import List


class Solution:
   # 查找x的父节点
    def find(self, x: int, fa: List[int]):
        if fa[x] != x: fa[x] = self.find(fa[x], fa)
        return fa[x]

    def process(self):
        n, m, k = map(int, input().split())
        col = [0] + list(map(int, input().split()))
        N = 3 * 10 ** 5
        fa = [i for i in range(N)]
        for i in range(m):
            l, r = map(int, input().split())
            a, b = self.find(l, fa), self.find(r, fa)
            fa[a] = b
        S = [list() for i in range(n + 10)]
        for i in range(1, n + 1):
            # 将每一个节点合并到对应的集合中方便后面操作
            S[self.find(i, fa)].append(i)
        res = 0
        for i in range(1, n + 1):
            if S[i]:
                # count用来计算当前集合中每一种气球颜色出现的次数
                count = dict()
                t = 0
                for x in S[i]:
                    if col[x] not in count:
                        count[col[x]] = 1
                    else:
                        count[col[x]] += 1
                    # 更新当前出现次数最多的颜色对应的出现次数
                    t = max(t, count[col[x]])
                # 将其余气球染成当前的颜色
                res += len(S[i]) - t
        return res


if __name__ == '__main__':
    print(Solution().process())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值