C

来源:互联网 发布:齐天大圣网络大电影 编辑:程序博客网 时间:2024/06/06 20:34

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 200005using 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个孩子