是中文题意 我就不赘述了(源代码在下面 压代码压得很厉害,不要吐槽)
13778373 | nailer | 1182 | Accepted | 568K | 250MS | C++ | 798B | 2015-01-13 17:50:18 |
通过总结网上的大神的解释 我总结了一篇笔记(以食物链为例,花了两节自习课,真是呵呵了)
我们用D-1(也就是输入中所给的1,2)表示x对y的关系
也就是 x和y同类 0
x吃y 1
x被y吃 2
假如我们设ty,tx为y,x的爹
那么通过列表我们可以得到如下的结论(其中TYPE 为0时x,y同类;为1时,x吃y)
type | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | ||||||||||
delta[x] | 0 | 0 | 0 | 1 | 0 | 1 | 2 | 2 | 1 | ||||||||||
delta[y] | 0 | 1 | 2 | 2 | 2 | 2 | 1 | 2 | 1 | ||||||||||
delta[ty] | 0 | 2 | 1 | 2 | 2 | 0 | 2 | 1 | 1 |
tx
|
x
之后我们可以得到如下代码(上面的那个表可以用笔来划一划,画成如上图一个类似矩形的玩意,标上方向更有利于下文的理解)
void link(int x,int y)
{
fa[ty]=tx;
d[ty]=(d[x]-d[y]+3+d-1)%3;
}
根据题目 我们知道一共只有3类动物 那么x,y一定存在着某种联系(来自poj的discuss),并且并查集中的一定有某种联系,不然并进来干吗?
那么我们可以用向量的知识来解答这道题
如果x->y的偏移量是0时 x,y是同类
如果x->y的偏移量是1时 x吃y
如果x->y的偏移量是2时 x被y吃
之后任意给出的两元素的关系便可以计算了
我们先分一下类
1 tx!=ty(ty和tx并无关系)
tx->ty = tx->x + x->y + y->ty(向量思想)
那么只需要把x,y按要求合并即可
2 ty==tx
x->y=x->tx+tx->y=x->tx+ty->y
那么x->y = (3-deltx[x]+deltx[y])%3
上述的值如果和d-1一致则为真 否则为假
好了好了,就这样了下面是源代码(不要纯抄)
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
//nailertt
int d[50010],fa[50010],x,y,f,ty,tx,ans=0,n,m;
int nailerfind(int x){
if(fa[x]!=x){int od=fa[x];fa[x]=find(fa[x]);d[x]=(d[x]+d[od])%3;}
return fa[x];}
void nailerbuild(int n){for(int i=1;i<=n;i++){fa[i]=i;d[i]=0;}}
void nailerlink(int x,int y){fa[ty]=tx;d[ty]=(d[x]-d[y]+3+f-1)%3;}
int solve(int f,int x,int y){
if(x>n||y>n){return 1;}
ty=find(y),tx=find(x);
if(f==1&&x==y){return 1;}
if(tx==ty){
if(f!=((3-d[x]+d[y])%3))return 1;
else return 0;
}
if(tx!=ty){
link(x,y);return 0;
}
}
int main()
{
scanf("%d%d",&n,&m);
build(n);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&f,&x,&y);
ans+=solve(f-1,x,y);
}
printf("%d",ans);
return 0;
}