食物链 - 洛谷【2024】

题目描述

题目描述

动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形。A 吃 B,B

吃 C,C 吃 A。

现有 N 个动物,以 1 - N 编号。每个动物都是 A,B,C 中的一种,但是我们并不知道

它到底是哪一种。

有人用两种说法对这 N 个动物所构成的食物链关系进行描述:

第一种说法是“1 X Y”,表示 X 和 Y 是同类。

第二种说法是“2 X Y”,表示 X 吃 Y 。

此人对 N 个动物,用上述两种说法,一句接一句地说出 K 句话,这 K 句话有的是真

的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。

• 当前的话与前面的某些真的话冲突,就是假话

• 当前的话中 X 或 Y 比 N 大,就是假话

• 当前的话表示 X 吃 X,就是假话

你的任务是根据给定的 N 和 K 句话,输出假话的总数。

输入输出格式

输入格式:

从 eat.in 中输入数据

第一行两个整数,N,K,表示有 N 个动物,K 句话。

第二行开始每行一句话(按照题目要求,见样例)

输出格式:

输出到 eat.out 中

一行,一个整数,表示假话的总数。

输入输出样例

输入样例#1:
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
输出样例#1:
3

说明

1 ≤ N ≤ 5 ∗ 10^4

1 ≤ K ≤ 10^5

题目分析

对于那种自己吃自己或者超出n的大小的

可以直接判断知道错误

然后i++再做下一次循环

如果两个条件都不满足 就判断这个是否和前面的话冲突

这里有一个公式

dis=x1-x2+x3

x1是x到父节点的距离 x2是y到父节点的距离

x3是题目中给的那个p  用这个公式来求两条不相连的路之间的距离

如果说两个点有关系 则需要将两个点的祖先节点合并到一起

如果给的数据(要判断是否冲突的)已经合并到一起了

就判断一下是否正确

这里用了一下 dis[x]-dis[y] 用它和t之间的关系 可以判断是否正确

最后就输出ans就可以了

错误

1.find函数未路径压缩 和 节点的距离进行压缩

  如果不这样做的话 y与父节点的距离就得不到全部的更新

2.p没减1

  因为自己定义的是0是同类 1是吃 2是被吃 和 题目中的1 2 正好多1

  所以在求距离的时候 p要减1 才能求出正确的距离

3.给dis[x]dis[y]赋值

  如果这样的话 dis[x]和dis[y]的值每一次循环的时候都会被附上1或者2

  其实dis里面所有变量的值都在求距离的时候求出来了

  所以无需对dis里面赋值

4.%3

  可能加上p后的值要大于3 也有可能求出距离是负数

  所以要加上3 %3 要保证距离是0 1 2中的一个

源代码

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 int find(int);
 7 void hb(int,int);
 8 int n,k,p,x,y,u,ans=0,father[50005],dis[50005];
 9 int main()
10 {
11 //    freopen("2024.txt","r",stdin);
12     scanf("%d%d",&n,&k);
13     for(int i=1;i<=n;i++)
14         father[i]=i;
15     memset(dis,0,sizeof(dis));
16     for(int i=1;i<=k;i++)
17     {
18         scanf("%d%d%d",&p,&x,&y);
19         if(x>n||y>n)
20             {
21             ans++;
22             continue;
23             }
24         if(p==2&&x==y)
25             {
26             ans++;
27             continue;
28             }
29         else
30         {
31             int r3,r4;
32             r3=find(x);
33             r4=find(y);
34             if(r3!=r4)
35             {
36                 int u=dis[y];
37                 hb(r3,r4);
38                 dis[r4]=(dis[x]-u+p-1+3)%3;
39             }
40             else
41                 if(x!=y)
42                 {
43                     int  t=(3+dis[x]-dis[y])%3;
44                     if(p==1&&t!=0)
45                         {
46                             ans++;
47                             continue;
48                         }
49                     if(p==2&&t!=2)
50                             ans++;
51                 }
52         }
53     }  
54     printf("%d",ans);
55     return 0;
56 }
57 int find(int m)
58 {
59     if(father[m]!=m)
60     {
61         int kk=father[m];
62         father[m]=find(father[m]);
63         dis[m]=(dis[m]+dis[kk])%3;    
64     }
65     return father[m];
66 }
67 void hb(int b,int d)
68 {
69     int r1,r2;
70     r1=find(b);
71     r2=find(d);
72     father[r2]=r1;
73 }

 

 

转载于:https://www.cnblogs.com/cls99/p/7410246.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值