【codevs1074】食物链
这个题……表示在伟大神犇lxt的指引下终于明白了qwq,lxt太神了orz
http://www.studyai.com/article/0d732f3e 丢一波神犇的博客
这个题普通的并查集是难以维护的(就算可以也是要开好几倍空间的扩展域并查集),所以这里主要写加权并查集
我们用0表示二者同类,1表示x吃y(它吃父亲),2表示y吃x(它被父亲吃) ,合并的时候需要在原来的关系值上加上相应的权值,利用向量加减的思想,我们可以比较容易的理解这个题(虽然它能应用的范围并不广泛)
#include<iostream> #include<cstdio> using namespace std; int n,k,fa[50050],v[50050],z,x,y,ans; int find(int x) { if(fa[x]==x) return x; int f=fa[x]; fa[x]=find(fa[x]),v[x]=(v[x]+v[f]+3)%3;//因为x现在指向祖宗,f指向祖宗,x原来指向f,可以利用向量运算 return fa[x]; } //用0表示二者同类,1表示x吃y(它吃父亲),2表示y吃x(它被父亲吃) int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=k;i++) { scanf("%d%d%d",&z,&x,&y); if(x>n||y>n)//特判 ans++; else if(x==y&&z==2) ans++; else { int qwq=find(x),qaq=find(y); if(qwq!=qaq) { if(z==1)//如果x与y是同类,那么说x祖宗的关系会受到y其祖宗对y的关系的影响,+3是为了防止出现负数,实际上应是+3+0 fa[qwq]=qaq,v[qwq]=(v[y]-v[x]+3)%3; else//如果x吃y,那么说它祖宗到y关系+1 fa[qwq]=qaq,v[qwq]=(v[y]-v[x]+4)%3; } else { if(z==2&&v[x]%3!=(v[y]+1)%3)//如果x吃y但是v[x]不等于v[y]+1(因为v[x]=(v[y]+1)%3) ans++; else if(z==1&&v[x]%3!=v[y]%3)//如果x与y是同类但是v[x]!=v[y](显而易见) ans++; } } } printf("%d",ans); }