食物链
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 101460 | Accepted: 30662 |
题目大意很简单理解
思路:用查并集,参考《挑战程序设计竞赛》思路,自己写了一份差不多的代码,代码中有注释
虽然这个题很老了,但个人感觉还是不错的
把三种类分成三组,但是这三组存在同一个数组里面分别是[1,n],[n+1,2*n],[2*n+1,3*n],
当比如1吃2,就是第一组的第一个和第二组的第二个合并,第二组的第一个和第三组的第二个合并,第三组的第一个和第一组的第二个合并,这就构成捕食关系,实质上都是1吃2.
当1和2同类时,就是同一组的第一个和第二个合并
最好用笔纸自己模拟一下,才好理解
代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int N=50005;
int a[3*N];
void inti()
{
for(int i=0;i<3*N;i++)
a[i]=i;
}
int find_root(int n)
{
return a[n]==n ? n : a[n]=find_root(a[n]);
}
void merge(int x,int y)
{
int r1,r2;
r1=find_root(x);
r2=find_root(y);
a[r1]=r2;
}
int same_root(int x,int y)
{
return find_root(x)==find_root(y);
}
//上面的函数都是查并集的模板,无关紧要,重点思路在下面
int main()
{
int n,k,d,x,y,ans;
scanf("%d%d",&n,&k);
ans=0;
inti();//初始化
while(k--)
{
scanf("%d%d%d",&d,&x,&y);
if(x>n ||y>n||x<=0||y<=0)//不满足条件的
{
ans++;continue;
}
if(d==1)//第一种情况
{
if(same_root(x,y+n) || same_root(x,y+n*2))//两个函数分别说明是否构成捕食和被捕食,如果既不是捕食,也不是被捕食,那么就是同类
ans++;
else
{
merge(x , y);
merge(x+n , y+n);
merge(x+2*n , y+2*n);
}
}
else//第二种情况
{
if(same_root(x,y) || same_root(x,y+2*n))//既不是同类也不是被捕食,那么就是捕食关系
ans++;
else
{
merge(x , y+n);
merge(x+n , y+2*n);
merge(x+2*n , y);
}
}
}
printf("%d\n",ans);
return 0;
}