ブルーブリッジカップ全国大会準備DAY3Ⅱ

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;
}

おすすめ

転載: blog.csdn.net/BOWWOB/article/details/109327822