经典题目是食物链相信大家应该知道
偏移量可以用有向线段来解决,lhq,xzp大神都说过这个,
a->b 为1表示 a吃b
a->b 为2表示 b被a吃
a->b->c
1 2
可以推出a与c同类
(1+2)%3=0,为同类
所以a->b反向线段为其正向线段相反数
所以可以解决掉这道题
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> const int MAXN=50007; int vis[MAXN],f[MAXN],n,k,ans=0; using namespace std; int find(int num) { if (f[num]!=num) { int pa=f[num]; f[num]=find(f[num]); vis[num]=(vis[num]+vis[pa])%3; } return f[num]; } int main() { scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) vis[i]=0,f[i]=i; for (int i=1;i<=k;i++) { int num,a,b; scanf("%d%d%d",&num,&a,&b); if (a>n||b>n||(n==2&&a==b)||a<1||b<1) //特别判断一下即可 { ans++; continue; } if (num==1) { int x=find(a),y=find(b); if (x==y) { if (vis[a]!=vis[b]) ans++; } else { vis[y]=(-vis[b]+0+vis[a]+6)%3;//这是通过有向线段推出来的 f[y]=x; } } else { int x=find(a),y=find(b); if (x==y) { if ((vis[a]-vis[b]+3)%3!=1) ans++; } else { vis[y]=(-vis[b]-1+vis[a]+6)%3;//同理,相同方法推理得知 f[y]=x; } } } cout<<ans<<endl; }
这是采用偏移量的方法,空间比较省,还是值得推荐的,详细纸上记录了,记录在A本上