AcWing 240.食物連鎖(基本アルゴリズムコース)
食物連鎖-トピックリンク
統合-実践の質問
#include <iostream>
using namespace std;
const int N=50000 +10;
int n,m;
int father[N];
//d[x]最终存储的是x点到根节点的距离
int d[N];
int res;
int find(int x){
if(father[x]!=x){
int t=find(father[x]);
//d[x]指 x到father[x]的距离
//d[ fahter[x] ] 指father[x]这个点到根节点的距离
//就是说x的父节点到根节点的距离。
//那么d[x]需要更新成 x到根结点的距离,即x到father[x]+father[x]到root的距离
//d[x]+d[ father[x] ]
d[x]+=d[father[x]];
//最后再更新当前点x的父节点为根节点root,压缩路径,不能提前压缩路径
//否则father[x]不再是原先x的父节点,而是最终的根节点root。
father[x]=t;
}
return father[x];
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
father[i]=i;
}
while(m--){
int q,a,b;
cin>>q>>a>>b;
int xx=find(a),yy=find(b);
if( a>n || b>n) res++;
else
if(q==1){
//a,b在同一个集合里,则可以推断a与b之间的关系。 若mod3不为0 则属于吃与被吃的关系,
//则推论与原话相反, 则这句话为假。
if(xx==yy && (d[a]-d[b])%3) res++;
else if(xx!=yy){
//不在同一个集合,因此为真话:a,b是同类
//因此先放入同一个集合里
father[xx]=father[yy];
//再设置a与b的距离为同类 类型的距离
d[xx]=d[b]-d[a];
}
}else if(q==2){
//在同一个集合里, 同样推理关系。
//a吃b
//a mod 3 的情况下 比b多1
// && 右边 若上述成立 则为0 则不会加,当不满足的时候才会加
if(xx==yy && (d[a]-d[b]-1)%3){
res++;
}else if(xx!=yy){
//不在同一集合,无法推论,则为真话
//因此先放入同一个集合里
father[xx]=father[yy];
//再设置a与b的距离为a吃b 类型的距离
d[xx]=1-d[a]+d[b];
}
}
}
cout<<res<<endl;
return 0;
}