您的位置:首页 > 其它

HPUOJ---2017寒假作业--专题1/F-食物链

2017-02-14 01:02 239 查看


    F - 食物链

 

动物王国中有三类动物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句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。 

1) 当前的话与前面的某些真的话冲突,就是假话; 

2) 当前的话中X或Y比N大,就是假话; 

3) 当前的话表示X吃X,就是假话。 

你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。 

Input
第一行是两个整数N和K,以一个空格分隔。 

以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 

若D=1,则表示X和Y是同类。 

若D=2,则表示X吃Y。

Output
只有一个整数,表示假话的数目。

Sample Input
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5


Sample Output
3

思路:(1)判断一句话的真假,意及判断那句话所对应的1或2的情况下,两个数字所代表的关系是否成立。成立,为真;反                           之,为假。
             (2)每一个数字所代表的动物有三种情况,干脆就3个n算了,不会打架了。第一个n都A,第二个n都B,第三个n 都C。                         三种生物之间的捕食关系构成一个循环,所以谁当主人公都是可以的。
              (3)d是1,表示判断两个是否同类,是要合并起来,一家人。d是2,表示判断两个捕食关系是否符合题目描述,是就                           合并,成仇敌。

#include<stdio.h>
int f[150000+11],t[150000+11];
int find(int x)
{
int r=x;
while(r!=f[r])
r=f[r];
int i=x,j;
while(i!=r)
{
j=f[i];
f[i]=r;
i=j;
}
return r;
}
void join(int x,int y)
{
int fx,fy;
fx=find(x);
fy=find(y);
if(fx!=fy)
f[fy]=fx;
}
int main()
{
in
4000
t n,k,i,j,d,x,y,num;
scanf("%d %d",&n,&k);
num=0;
for(i=1;i<=3*n;i++)                  //每一个数字所代表的动物都有三种可能,所以干脆设1到n是A,n+1到2n是B,2n+1到3n是C。
f[i]=i;                          //赋初值
for(i=1;i<=k;i++)
{
scanf("%d%d%d",&d,&x,&y);
if(x<1||y<1||x>n||y>n)
{
num++;
continue;     //数字超出范围,直接下次循环呗
}
if(d==1)    //需要是同类的哦
{
if(find(x)==find(y+n)||find(x)==find(y+2*n))//根节点一样,表示同类 ,如果if语句成立,那么x和y肯定不同类,假话
num++;
else
{
join(x,y);
join(x+n,y+n);
join(x+2*n,y+2*n);    //同类合并,兄弟
}
}
else if(d==2)                  //必须符合江湖规矩
{
if(find(x)==find(y)||find(x)==find(y+2*n))     //根节点一样,表示不同类 ,而且有前面吃后面的关系,显然和题目叙述的不符合,假话
num++;
else
{
join(x,y+n);
join(x+n,y+2*n);
join(x+2*n,y); //不同类,按照题目所述关系合并,吃与被吃的关系。
}
}
}
printf("%d\n",num);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: