C - Socks

C - Socks

题目链接

题意为:
Arseniy的妈妈要外出m天,给他准备了n只袜子,并且备注好了第几天穿哪两只袜子。但Arseniy发现,如果按照妈妈的备注穿袜子,会有一些天穿不同颜色的袜子,穿出去会被耻笑。于是,他准备了k种颜料,如果袜子颜色不相同,他会涂成相同颜色。他想知道最少改变几只袜子的颜色,穿出去不会被人笑话。
输入:
n, m, k
接下来一行有n个数,代表n个袜子的颜色
接下来有m行,代表每一天需要穿第几只袜子
输出:
the minimum number of socks that should have their colors changed
他需要改变的最少袜子数

#include <stdio.h>
#include <string.h>
#include <map>
#define N 200005
using namespace std;
map<int, int>tree[N];
int f[N]={0};//并查集祖先
int cnt[N];//名下的子孙个数
int getf(int t)//找祖先
{
    if (f[t] == t)
        return t;//祖先就是自己本身
    else
    {
        f[t] = getf(f[t]);//继续往前找,直到找到祖先
        return f[t];//返回祖先
    }
}
void merge(int l, int r)//合并
{
    int t1, t2;
    t1 = getf(l);//找祖先
    t2 = getf(r);
    if (t1 != t2)//不是同一个祖先
    {
        f[t2] = t1;//靠左原则,把左边变为右边祖先,即t2的祖先是t1
        cnt[t1] += cnt[t2];//把以t2为祖先的数全部加入t1名下
    }
    return ;
}
int main()
{
    int n, m, k, i, l, r, vis[N];
    int max[N];//同一祖先下颜色相同袜子的最多数
    int color[N];
    memset(max, 0, sizeof(max));
    memset(vis, 0, sizeof(vis));
    scanf("%d %d %d", &n, &m, &k);
    for (i = 1; i<= n; i++)
    {
        scanf("%d", &color[i]);
        f[i] = i;
        cnt[i] = 1;
    }
    for (i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        merge(l, r);
    }
    for (i = 1; i <= n; i++)
    {
        int root = getf(i);//祖先
        tree[root][color[i]]++;//同一祖先下的袜子的不同颜色的个数
        if (tree[root][color[i]] > max[root])
            max[root] = tree[root][color[i]];
    }
    int sum = 0;
    for (i = 1; i<= n; i++)
    {
        int root = getf(i);
        if (!vis[root])
        {
            vis[root] = 1;
            sum += cnt[root] - max[root];
        }
    }
    printf("%d\n", sum);
    return 0;
}

用并查集:将每天有联系的袜子(就是可能在同一天穿的袜子)构成树,然后组成森林,然后在一棵树上染袜子,将所有的袜子染成这个树上颜色
最多的那种颜色,然后累加

例子:
“`sequence
子树1——–>(1【1】,3【1】,5【2】,6【2】,7【3】)
子树2——–>(8【1】,9【1】,10【1】,2【2】,4【2】)

注释:
【】里为袜子颜色

tree[1][1] = 2; //有2个1号颜色的袜子
tree[1][2] = 2; //有2个2号颜色的袜子
tree[1][3] = 1; //有1个3号颜色的袜子
//以1为祖先的子树中袜子的颜色分布

tree[8][1] = 3; //有3个1号颜色的袜子
tree[8][2] = 2; //有2个2号颜色的袜子
tree[8][3] = 0;
//以8为祖先的子树中袜子的颜色分布

max[1] = 2; //代表以1为祖先的子树中,相同颜色袜子的个数最多为2
max[8] = 3; //代表以8为祖先的子树中,相同颜色袜子的个数最多为3

cnt[1] = 5; //以1为祖先的子树有5个孩子
cnt[8] = 5; //以8为祖先的子树有5个孩子

发布了29 篇原创文章 · 获赞 4 · 访问量 4708

猜你喜欢

转载自blog.csdn.net/onion___/article/details/78681699