首页 > 其他分享 >洛谷P2024 [NOI2001] 食物链

洛谷P2024 [NOI2001] 食物链

时间:2022-12-24 11:12:00浏览次数:47  
标签:关系 P2024 洛谷 食物链 int fa 动物 NOI2001 tmp

slojP2577. 食物链

题目大意

说实话,我做对了之后都还是有点懵

语文不好都这么招歧视了吗,我太难了

三类动物 A,B,C,A 吃 B,B 吃 C,C 吃 A。给出若干关系,判断第几个关系是错误的。(貌似不太准确)

很显然, 对假话条件 2、3 自己去原题目中看的处理十分简单,只要在读入数据时作两个条件判断即可解决

题目的主要任务在于处理条件1

从表面上看, 条件1的处理似乎也没有什么难度:

一个动物无非就是 A,B,C 三类

而 A,B,C 之 间的食物链关系是一对一单向环形的

也就是说如果已知动物 X 所属种类和 X、Y 之间的食物链关系

就一定可以确定出动物 Y 的种类

同时某个动物具体属于哪一类并不影响本题的结果

而只要求它与其他动物关系的相对位置正确即可

于是, 我们有一个大胆的思路

不妨开3个数组A,B,C, 分别记录着三种类的成员

首先假设第一句有效话中的动物X为A类,将其放入数组A

倘若Y与X同类, 则把Y也放入A;

若Y被X吃,则将Y放入B,如此反复操作所有的有效话,就可以确定每个动物的种类,并容易统计出假话的个数。

问题似乎已经圆满地解决了也只是似乎,顺带说一句,上面那么一串思路我也没写不知道实际行不行,读者可自行尝试

但是,上面的这个算法存在着重大的错误

对于一个未知属性的生物我们都采取的是定义为 A 类型,这样子显然是有问题的。但有概率能解决这道题

这个算法只能当每一句话都可直接与此前已知的食物链建立明确关系的时候才能使用。

明确了上面这个关系,我们就不难从刚才的算法扩展出另一种算法:

对于目前关系未知的动物X,我们为他新开辟一条食物链A2,B2,C2

显然,在这个新的组中,动物X所在的种类也是随意的,

于是假设它在A2组,这样,所有与X的关系就可用与算法1同样的方式加入这个组中,

而这个组与原先的组 A1,B1,C1 的关系是不确定的。

如此反复,我们也可以得到组 3、组 4、组 5……,

一旦有一句话牵涉到某两个组的成员之间的食物链关系,

我们就依据一定的换算规则将这两个组合并起来,以保证关系网的完整性。

通过上面的分析,并查集在本题中的运用已经呼之欲出。

一个集合有三类的元素,合并集合的时候,需要对三类元素进行合并。

当然,肯定没几个人真的在代码中写出三个类别

而是会将元素之间的关系采用数字表示,

在这里,我用0表示与父亲元素同族,1表示吃父亲元素,2表示被父亲元素吃

可以以数学的方式在路径压缩时快捷的改掉关系

#include<bits/stdc++.h>
using namespace std;
int fa[50010],d[50010],ans,n,m;
int find_(int x){
    if(x!=fa[x]){
        int t = fa[x];
        fa[x] = find_(fa[x]);
        d[x] = (d[x]+d[t])%3;
    }
    return fa[x];
}
void merge(int x,int y,int tmp){
    int rootx = find_(x);
    int rooty = find_(y);
    if(rootx==rooty){
        if((tmp-1)!=(d[x]-d[y]+3)%3)
            ans++;
    }else{
        fa[rootx] = rooty;
        d[rootx] = (d[y]-d[x]+tmp-1)%3;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1;i<=n;i++)
        fa[i] = i;
    for(int i = 1;i<=m;i++){
        int tmp,x,y;
        scanf("%d%d%d",&tmp,&x,&y);
        if(x>n||y>n||(tmp==2&&x==y))  ans++;
        else merge(x,y,tmp);
    }
    printf("%d",ans);
    return 0;
}

 

标签:关系,P2024,洛谷,食物链,int,fa,动物,NOI2001,tmp
From: https://www.cnblogs.com/cztq/p/17002491.html

相关文章

  • 洛谷P1196 [NOI2002] 银河英雄传说
    slojP2577.食物链题目大意一个序列初始编号为1,2,3,,,30000有2个操作:mij合并第i列和第j列,将第i列头部接到第j列尾部cIj询问i号和j号之间的数量,若......
  • Solution -「COCI 2009-2010」「洛谷 P8076」RESTORAN
    \(\mathscr{Description}\)  Link.  给定一个含\(n\)个点\(m\)条边的简单图,求一种边二染色方案,使得所有\(\deg\ge2\)的结点都邻接于两种颜色的边.  \(n......
  • AcWing341. 洛谷P1073, NOIP2009 最优贸易
    AcWing题目传送门洛谷题目传送门题目大意\(~~~~~~\)一个投机倒把的奸商想要通过城市不太健全的贸易系统坑点钱,任意城市都可以买入或者卖出水晶球,他想尽量在便宜的城市买......
  • 洛谷 P2679 [NOIP2015 提高组]子串
    \(70pts\):记\(sub_A(i)\)表示\(A\)的前\(i\)个字符构成的子串,相应地,\(sub_B(i)\)为\(B\)的前\(i\)个字符构成的子串。设\(f(i,j,k)\)表示在\(sub_A(i......
  • 洛谷P2680 运输计划(LCA + 二分 + 树上边差分)
    洛谷P2680运输计划​ 现在有一棵树,每条树边上都有正权值。接下来,有m个询问,每次询问给出两个结点,这两个结点之间有一条路径。现在你可以任选一条树边,将其边权置为0,请输......
  • 洛谷 P5401 [CTS 2019] 珍珠 题解
    题目链接令\(c_i\)表示第i种颜色的珍珠的数量,显然我们最多能装的瓶数是\(\sum\lfloor\frac{c_i}2\rfloor\)。也就是说,\(c_i\)为奇数的\(i\)的数量不能太多,这个数量要......
  • 洛谷 P6580 [Ynoi 2019] 美好的每一天~ 不连续的存在 题解
    既然是YNOI那肯定是要分块的。先考虑树是一条链的情况,可以直接回滚莫队,对n个节点组成的序列分块。在回滚莫队的过程中,当前维护的区间一共会扩展\(O(n\sqrtn)\)次,每次都是......
  • 洛谷 P1712 [NOI2016] 区间
    很多套路糅合在一起的一道题。记\(len_i=r_i-l_i\)。则所求转化为一个有\(m\)个区间的集合\(S\),满足:存在一个\(x\),使得对于所有\(S\)中的区间\(i\),有\(l_......
  • 洛谷P3224 [HNOI2012]永无乡 题解 splay tree 启发式合并
    题目链接:https://www.luogu.com.cn/problem/P3224主要知识点是:树上启发式合并,即每次合并将小的树里面的每个点合并大大的树里面,时间复杂度\(O(n\log^2n)\)。同时需要......
  • 洛谷-P1450 硬币购物
    P1450硬币购物容斥||\(dp\)+单调队列优化容易看出是个多重背包,然后拿单调队列优化一下后,计算量为\(O(4ns)\)这种做法的话就是单调队列优化板子题#include<bits/......