• CF-1209D Cow and Snacks (并查集,图)


    原题链接:

    题意:

    有N个甜点,和M头牛。每头牛对应有两种喜欢的食物,当牛能够吃到自己喜欢的食物,就会开心,否则不开心。同时每只牛去吃甜点时,会把他喜欢的都吃掉,即只要剩下他喜欢的,他都会吃掉。

    现在问至少有多少牛会伤心。

    思路:

    如果读题不仔细,或许就会往 二分图匹配,网络流这些地方去想(因为都可以解决匹配问题)。但是这里有些不同,即是 一头牛可能会吃多个(多匹配)。不过往图的方向思考的确是正确的。

    由于每只动物都有两个最喜欢的零食,这暗示我们应该将问题建模为图。 节点是小吃,边是动物与其喜欢的甜点(动物没有结点)。
    让我们考虑一个大小大于1的图的连通分量
    吃该组分的第一个动物(边)必须吃两个零食(节点),所有其他零食节点将被一个动物吃掉(边连接)。 总是可以找到一个订单,这样其他动物就不会吃两个零食(例如,BFS序列)。 因此,具有c个顶点的连通分量最多可以满足c-1动物。
    N为小吃的数量,M是动物的数量,C是连接组件的数量(包括大小为1的组件)。 满意动物的数量是N-C,因此不快乐动物的数量是M-(N-C)。

    所以这个图论模型关键在于 ,把动物抽象成边,甜点抽象成结点。吃,即意味着将结点进行连接,最后最多有多少条边能够连接完这些点

    code:

    #include <bits/stdc++.h>
    const int maxn = 1e5+7;
    const int maxm = 1e6+7;
    const int mod = 1e9+7;
     
    int pre[maxn];
    int sz[maxn];
    int find(int x){
        return pre[x]==x?pre[x]:find(pre[x]); 
    }
    void unite(int x, int y)
    {
        int px = find(x), py = find(y);
        if (px == py) return ;
        else if (sz[px] > sz[py])
        {
            pre[py] = px;
        }
        else
        {
            pre[px] = py;
            if (sz[px] == sz[py]) sz[py]++;
        }
    }
     
    bool same(int x, int y)
    {
        int px = find(x), py = find(y);
        return px == py;
    }
    void init(int n){
        for(int i=0;i<=n;i++){
            pre[i]= i;
            sz[i] =1;
        }
    }
    int main(){
        int n,m;
        cin>>n>>m;
        init(n);
        int cnt = 0;
        for(int i=0;i<m;i++){
            int u,v;
            cin>>u>>v;
            if(!same(u,v)){
                unite(u,v);
                cnt++;
            }
        }
        cout<<m-cnt<<endl;
        return 0;
    } 
  • 相关阅读:
    进程池线程池
    线程与其操作方法
    生产者消费者模型
    Java反射机制详解
    ajax跨域原理以及解决方案
    数据库连接池的选择 Druid
    新目标
    让webstorm支持avalon语法自动补全
    使用IDEA和gradle搭建Spring MVC和MyBatis开发环境
    使用IDEA自带的rest client参数传递乱码问题
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11523176.html
Copyright © 2020-2023  润新知