D. Cow and Snacks 并查集

Posted -citywall123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D. Cow and Snacks 并查集相关的知识,希望对你有一定的参考价值。

 

D. Cow and Snacks

技术图片

 

题意:有n种小吃,m个人,每个人有两种喜欢的小吃,当一个人遇到两种自己都喜欢的小吃,可以都吃掉,问在最优的吃小吃顺序下,不能吃到自己喜欢的小吃的人数最少是多少?

 

题解:把n种小吃当作n个点,m个人当作m条边,每个连通图里面第一个吃的人,一定是可以吃两种自己喜欢的小吃。每次判断这条边是否在已有的联通图里面,对已经在连通图里面的边,是一定不能吃到小吃,若不在连通图里面,则一定可以吃到小吃,用cnt统计可以吃到小吃的人数,最后m-cnt就是答案

 

#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
using namespace std;
int p[1000005], r[1000005];
int n,t=0;
void init()//初始化集合,每个元素的老板都是自己

    for (int i = 1; i <= n; i++)
    
        p[i] = i;
    


int find(int x)//查找元素x的老板是谁

    if (x == p[x])
        return x;
    else
        return p[x] = find(p[x]);


void join(int x, int y)//合并两个集合

    int xRoot = find(x);
    int yRoot = find(y);

    if (xRoot == yRoot) //老板相同,不合并
        return;
    //cnt=cnt-1;
    if (r[xRoot] < r[yRoot]) //r[i]是元素i所在树的高度,矮树的根节点认高树的根节点做老板
        p[xRoot] = yRoot;
    else if (r[xRoot] > r[yRoot])
        p[yRoot] = xRoot;
    else
    
        p[yRoot] = xRoot;//树高相同,做老板的树高度要加一
        r[xRoot]++;
    


bool sameRoot(int x, int y)//查询两个元素的老板是否相同

    return find(x) == find(y);

//这里也可以用cnt求不同子集个数,初始化cnt=n,每加入一条边,cnt=cnt-1;
int main()

    ios::sync_with_stdio(false);
    int m,cnt=0;
    cin>>n>>m;
    init();
    for(int i=0;i<m;i++)
    
        int x,y;
        cin>>x>>y;
        if(!sameRoot(x,y))
        
            join(x,y);
            cnt++;
        
    
    cout<<m-cnt<<endl;
    return 0;

 

以上是关于D. Cow and Snacks 并查集的主要内容,如果未能解决你的问题,请参考以下文章

并查集并查集专题总结

并查集并查集

Codeforces Round #396 (Div. 2)D. Mahmoud and a Dictionary(带权并查集)

Codeforces Round #396 (Div. 2)D. Mahmoud and a Dictionary(带权并查集)

codeforces#766 D. Mahmoud and a Dictionary (并查集)

Codeforces 437 D. The Child and Zoo 并查集