食物链(变态)

洛谷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

解题思路

1.弱智错误

先排除弱智错误

p==2&&x==y

x>n||y>n

2.分类讨论

p==1时。。。。。。

p==2时。。。。。。

用0表示同类

用1表示A吃B

用2表示A被b吃

重点:

看图

代码如下(两种方法)

方法1(世杰比特牛版)

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

方法2(自制版)

#include<cstdio>
#include<cstring> 
#include<iostream>
using namespace std;
int find(int);
void unionn(int,int);
int n,k,x,y,father[50005],p,dis[50005],cnt=0,f;
int main()
{
    //0 同类
    //1 A吃B
    //2 C被A吃
    //freopen("2024.txt","r",stdin);
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++)
    father[i]=i;
    memset(dis,0,sizeof(dis));
    for(int i=1;i<=k;i++)
    {
        scanf("%d%d%d",&p,&x,&y);
        if((x>n||y>n)||(x==y&&p==2))
            {cnt++;
            continue;}
        if(p==1)
        {
            int r1=find(x);
            int r2=find(y);
            if(r1==r2)
            if(dis[x]!=dis[y])
            {
                cnt++;
                continue;
            }
            dis[father[x]]=(dis[y]-dis[x]+6)%3;
            father[father[x]]=father[y];
        }    
        if(p==2)
        {
            int r1=find(x);
            int r2=find(y);
            if(r1==r2) 
            if(dis[x]!=(dis[y]+1)%3)
            {
                cnt++;
                continue;
            }
            dis[father[x]]=(dis[y]-dis[x]+4)%3;
            father[father[x]]=father[y];
        }
    }
    printf("%d",cnt);
}
int find(int x)
{
    if(x!=father[x])
    {
        int xx=father[x];
        father[x]=find(father[x]);
        dis[x]=(dis[x]+dis[xx])%3;
    }
    return father[x];
}
void unionn(int r1,int r2)
{
    father[r2]=r1;
}

 

posted @ 2017-08-22 10:34  frime+  阅读(188)  评论(0编辑  收藏  举报