• 【POJ】[1182]食物链


    这里写图片描述
    这里写图片描述

    也是因为OJ问题卡主了几天的一个题
    复制一下当时写的时候写的一些想法

    不矛盾的情况下
    x,y同类 则 xA-yA xB-yB xC-yC 可以合并
    x吃y 则 xA-yB xB-yC xC-yA 可以合并

    并查集 体现在

    把关系可以成立的合并
    那么通过查询两元素是否为同一集合
    则可推断这一关系是否可以成立
    “当前的话与前面的某些真的话冲突,就是假话;”

    如果对于当前的话有矛盾的集合关系已经成立
    (已经在同一集合)
    那么这句话自然是假话

    所以可以用并查集的思想来做

    这里用到并查集是因为并查集的两个操作
    “合并”可以变为一个集合的关系
    “判断”在不在同一集合

    所以综合以上思考
    只需要把每一个动物都分成ABC三种考虑
    然后对整体进行并查集操作即可

    毕竟是找出假话
    所以有的话只要不能判断是错的
    便可以把它当成对的
    故可以把全部的情况都综合来进行考虑

    (也就是说到最后判断出的“假话”是那些一定错的话)

    此处把
    1~N 设为 可能为A的情况
    N+1~N+N 设为 可能为B的情况
    N+N+1~N+N+N 设为 可能为C的情况

    需要注意的是ABC并非狭义上的固定种类
    而是由于ABC都是假定的
    所以不存在顺序问题

    也就是内心把它理解为
    1~N 设为 可能为B的情况
    N+1~N+N 设为 可能为C的情况
    N+N+1~N+N+N 设为 可能为A的情况
    也未尝不可

    主要是满足A->B->C->A的三角关系便可以了
    这也是为什么程序里两个
    关于 D==1 D==2 的if
    只判断了 X
    不需要对应判断 X+N X+2N 的原因

    这一题需要注意的是在POJ上如果使用
    while(scanf("%d %d",&N,&K)!=EOF) { }
    也就是允许多次输入的话会WA
    所以AC代码改成了只允许输入一次 N K

    #include<stdio.h>
    int par[150150];
    int rank[150150];
    int find(int m) {
        if(par[m]==m)
            return m;
        else
            return par[m]=find(par[m]);
    }
    void unite(int x,int y) {
        x=find(x);
        y=find(y);
        if(x==y)
            return;
        if(rank[x]<rank[y])
            par[x]=y;
        else {
            par[y]=x;
            if(rank[x]==rank[y])
                rank[x]++;
        }
    }
    int main() {
        int N,K;
        scanf("%d %d",&N,&K);
            for(int i=1; i<=3*N; i++) {
                par[i]=i;
                rank[i]=0;
            }
            int cnt=0;
            while(K--) {
                int D,X,Y;
                scanf("%d %d %d",&D,&X,&Y);
                if(X<1||Y<1||X>N||Y>N) {
                    cnt++;
                    continue;
                }
                if(D==1) {
                    if(find(X)==find(Y+N)||find(X)==find(Y+N+N))
                        cnt++;
                    else {
                        unite(X,Y);
                        unite(X+N,Y+N);
                        unite(X+N+N,Y+N+N);
                    }
                } else {
                    if(find(X)==find(Y)||find(X)==find(Y+N+N))
                        cnt++;
                    else {
                        unite(X,Y+N);
                        unite(X+N,Y+N+N);
                        unite(X+N+N,Y);
                    }
                }
            }
            printf("%d
    ",cnt);
    
        return 0;
    }

    题目地址:
    【POJ】[1182]食物链
    因为POJ上述指出的判题问题
    所以附一个NYOJ的地址
    【NYOJ】[207]食物链
    NYOJ这一题写成多组输入不会WA

  • 相关阅读:
    计算与软件工程作业一
    《CLSZS团队》:团队项目选题报告
    计算与软件工程第五次作业
    计算与软件工程第四次作业
    计算与软件工程代码规范
    计算与软件工程第三次作业
    计算与软件工程第二次作业
    壹贰叁肆团队项目选题报告
    计算与软件工程 作业五
    计算与软件工程 作业四
  • 原文地址:https://www.cnblogs.com/BoilTask/p/12569839.html
Copyright © 2020-2023  润新知