首页 > 其他分享 >食物链

食物链

时间:2024-09-08 18:14:03浏览次数:1  
标签:食物链 dist int px py 距离 节点

先看题目要求


算法1

(并查集维护关系)

1.由题意可知只有三种动物,三种动物之间的关系是循环的(由于是环形),可以通过对3取模判断是哪一种关系

2.可以利用并查集维护这三种动物值间的关系,也就是说集合表示的是每一个点根节点距离

因此需要一个数组,记录每一个点到根节点的距离,从而可以推断出任意两点之间的关系 (一个点到根节点的距离 % 3)

3.一共有三种关系:

1)与根节点的距离为 1 (余1) ,表示该点吃根节点

2)与根节点距离为 2 (余2), 表示他被根节点吃

3)与根节点距离为 0 (余0),表示该点与根节点是同一类

代码实现细节

1.初始化:

一开始所有动物都是独立的一个集合,并且自己到自己的距离为 0

int dist[N];    //全局变量默认值就是0

for(int i=1;i<=n;i++){
    p[i]=i;    //并查集初始化
}

2.路径压缩的同时,需要更新距离:

从他到父节点的距离 + 父节点到根节点的距离 = 他到根节点的距离

int find(int x){
    if(p[x] != x)   //如果不是父节点
    {   
        int fu = find(p[x]);   //找根节点
        
        dist[x] += dist[p[x]];  //他到根节点的距离
        
        //dist[p[x]] 就是父节点到根节点的距离
        
        p[x] = fu;   //父节点指向根节点 - 路径压缩
    }
}

3.判断同类关系:

1.属于同一个集合两个点到根节点的距离模3结果一样,表示同一类

dist[x]% 3 == dist[y]% 3
dist[x]% 3 - dist[y]% 3 == 0
(dist[x] - dist[y] )%3 == 0

2.不属于一个集合时,首先合并两个集合,更新根节点到另一个根节点的距离

int px = find(x), py - find(y);

if(px!=py){
    p[px] = py;   //合并两个集合,将py 成为 px的根节点
    dist[px] = dist[y] - dist[x];   //更新px到 py的距离
}

如何求px到py的距离

合并之后到两个集合根节点的距离相同

(dist[x] + ?)% 3 == dist[y]% 3
dist[x] +? == dist[y]
? = dist[y] - dist[x]

4.判断吃与被吃关系:

比如: X 吃 Y

1.属于一个集合时,x到根节点的距离比y到根节点的距离多1,因为x 到 y 的距离为 1

因此,判断x-1到根节点的距离是否等于 y到根节点的距离即可

(dist[x]-1)% 3 == dist[y]% 3
(dist[x]-1)% 3 - dist[y]% 3 == 0
(dist[x] - 1 - dist[y] )%3 == 0

2.不属于一个集合,首先合并两个集合,在更新根节点到另一个根节点的距离

((dist[x] - 1) + ?)% 3 == dist[y]% 3
(dist[x] - 1) +? == dist[y]
? = dist[y] - dist[x] + 1

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6+10;

int n,m;
int p[N];  //并查集
int dist[N];  //该点到根节点的距离
int res;

int find(int x){
    if(p[x]!=x){
        int fu = find(p[x]);  //找根节点
        dist[x] += dist[p[x]]; 
        p[x] = fu;
    }
    return p[x];
}
int main(){
    scanf("%d%d",&n,&m);
    
    for(int i=1;i<=n;i++)  p[i]=i;
    
    while(m--){
        int op,x,y;
        scanf("%d%d%d",&op,&x,&y);
        
        if(x > n || y > n) {
            res++;
            continue;
        }
        
        int px = find(x), py = find(y);
        
        if(op==1) {  
         
            if(px==py && (dist[x]-dist[y])%3 ) res++;
            else if(px != py){
                p[px] = py;  
                dist[px] = dist[y] - dist[x]; 
            }
        }else {
            if(px==py && (dist[x] - 1 -dist[y]) % 3) res++;
            else if(px != py){
                p[px] =py;
                dist[px] = dist[y] - dist[x] + 1;
            }
        }
    }
    
    printf("%d",res);
    return 0;
}



标签:食物链,dist,int,px,py,距离,节点
From: https://www.cnblogs.com/ltphy-/p/18403195

相关文章

  • 题解_P2024 [NOI2001] 食物链
    [NOI2001]食物链题目描述动物王国中有三类动物\(A,B,C\),这三类动物的食物链构成了有趣的环形。\(A\)吃\(B\),\(B\)吃\(C\),\(C\)吃\(A\)。现有\(N\)个动物,以\(1\simN\)编号。每个动物都是\(A,B,C\)中的一种,但是我们并不知道它到底是哪一种。有人用两种说法对这......
  • P2024 [NOI2001] 食物链
    原题链接题解关系具有矢量特性,因此可以带权并查集维护code#include<bits/stdc++.h>#definelllonglongusingnamespacestd;intfa[50006];intval[50006];intfinds(intnow){if(now==fa[now])returnnow;inttem=fa[now];fa[now]=finds(fa[now])......
  • [lnsyoj110/luoguP2024]食物链
    题意原题链接三类元素\(a,b,c\)满足\(a\tob\),\(b\toc\),\(c\toa\)。现在共有\(n\)个元素,给出\(m\)条关系\(x\toy\)或\(x\)与\(y\)种类相同,输出非法或与前面所属关系相矛盾的关系数量sol并查集可以处理“朋友的朋友是朋友”这样的传递关系,却不能处理“敌人......
  • Acwing240食物链
    题目动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形。A 吃 B,B 吃 C,C吃 A现有 N 个动物,以 1∼N 编号。每个动物都是 A,B,C中的一种,但是我们并不知道它到底是哪一种。有人用两种说法对这 N 个动物所构成的食物链关系进行描述:第一种说法是......
  • 食物链题解
    由题得,所有动物整体关系如上。起初每个动物相互时间没有关系,bb[i]=i。对于x与y:如果它们是同类即x到y的距离为$0$,或者转了几圈,一圈距离为$3$,即模$3$余$0$。如果x捕食y,就是x到y距离模$3$余$1$。对x与y操作时:如果它们没有关系(它们不被之前给出的某......
  • 洛谷P4017 最大食物链计数
    题目信息题目要求样例输入/输出 算法简介 要知道题目需要用到什么样的算法,首先得捋清楚题目的意思比如这个题目,我们读题后可以获得这样的信息:(1)节点之间构成有向边(2)所有边不会构成环(3)需要求的所有的边没有边权而且一定是从入度为零的节点到出度为零的节点基......
  • P2024 [NOI2001] 食物链
    原题链接题解带权并查集的应用,普通的并查集只能表示结点间的一种关系(如同一集合中的都是朋友)。而带权并查集的结点权值表示该结点与根结点的关系。相对应,带权并查集的路径压缩也复杂了一点。code #include<bits/stdc++.h>usingnamespacestd;constintN=5e4+5;intn,k......
  • P2024 [NOI2001] 食物链
    Solution:使用拓展域并查集,\(1-n\)表示\(\rmA\)群落,\(n+1-2n\)是\(\rmB\)群落,\(2n+1-3n\)是\(\rmC\)群落那么对于操作一,我们首先判断\(x\)是否吃了\(y\)或\(y\)是否吃了\(x\).若吃了,那么这句话为假若没吃,则将(x,y)(x+n,y+n)(x+2n,y+2n)三条边连......
  • 洛谷题单指南-图的基本应用-P4017 最大食物链计数
    原题链接:https://www.luogu.com.cn/problem/P4017题意解读:食物链的顶端不会被其他生物吃,在图结构中设定为入度是0,食物链的底端不会吃其他生物,在图结构式设定为出度是0,此题就是要计算所有入度是0的点到所有出度是0的点一共有多条路径。解题思路:首先,来模拟一样样例,样例数据形成的......
  • P4017 最大食物链计数
    原题链接题解首先这题是一个有向无环图,如图,每个结点上方显示的是到达该节点的路径数,我们不难发现每个结点的路径数都由其入度结点的路径数之和,最终得出5结点的路径数。那么由此我们只需要求出每个无出度结点的路径数再相加即可。 code #include<bits/stdc++.h>usingnam......