• poj 1182 食物链 种类并查集


    食物链

    题意:"1 X Y",表示X和Y是同类;"2 X Y",表示X吃Y;输入N(1 <= N <= 50,000),(0 <= K <= 100,000)表示最多有N个动物,同时有K句话。

    如果当前的话与前面的话不矛盾就说当前的话是正确的;(无罪判定)问这K句话中有几句是假话;

     

    思路:很裸的种类并查集,只是里面穿插了三种关系,即同类,A吃B,B吃A;其实看了数组的范围[3*N]和x+N,x+2*N就知道思路了;即x吃x+N;类推

    对于判定是否是同类时,不要直接求解,因为这与初始化违背;这是利用无罪假设,不冲突即可,即x不与y+N,y+2*N同类即可合并x和y;

    同理判断x是否吃y,不要直接判断x是否与y+2*n在同一个集合中,而是看反面是否成立;每次处理合并三种关系即可;

    ps:千万别开始就陷入思维定式,认为要将每种同类弄成0,1,2然后0吃1..这种,因为这种初始化很难,并且对于开始输入很多同类时,不知道给这些同类赋几;

    Memory: 1280K        Time: 297MS
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<stdlib.h>
    #include<time.h>
    using namespace std;
    #define rep0(i,l,r) for(int i = (l);i < (r);i++)
    #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
    #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
    #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
    #define MS0(a) memset(a,0,sizeof(a))
    #define MS1(a) memset(a,-1,sizeof(a))
    const int MAXN = 50050;
    int f[MAXN*3];
    int Find(int a)
    {
        return a==f[a]?f[a]:f[a]=Find(f[a]);
    }
    bool sample(int a,int b)
    {
        return Find(a) == Find(b);
    }
    void _union(int a,int b)
    {
        a = Find(a),b = Find(b);
        f[a] = b;
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        int tot = 3*n,ans = 0;
        rep1(i,0,tot) f[i] = i;
        rep1(i,1,m){
            int D,x,y;
            scanf("%d%d%d",&D,&x,&y);
            if(x > n || y > n) ans++;
            else{
                if(D&1){
                    if(sample(x+n,y) || sample(x+n+n,y)) ans++;
                    else{
                        _union(x,y);
                        _union(x+n,y+n);
                        _union(x+n+n,y+n+n);
                    }
                }
                else{
                    if(sample(x,y) || sample(x+n+n,y)) ans++;
                    else{
                        _union(x+n,y);
                        _union(x+n+n,y+n);
                        _union(x,y+n+n);
                    }
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Vmware 添加虚拟磁盘
    2019-2020-2 《网络对抗技术》 Exp3 免杀原理与实践
    Docker 容器更换软件源
    Docker 查看容器 Linux 版本
    OpenMediaVault 5 进阶配置(四) Portainer 管理 Docker
    Portainer 中文文档:部署
    树莓派 部署 Docker 数据库容器
    通过Cookie统计上次网页访问时间
    用JavaMail通过QQ邮箱来发送邮件(第一篇博客,备忘)
    删掉双系统
  • 原文地址:https://www.cnblogs.com/hxer/p/5184816.html
Copyright © 2020-2023  润新知