• poj1182 食物链 带权并查集


    题目传送门

    题目大意:大家都懂。

    思路:

      今天给实验室的学弟学妹们讲的带权并查集,本来不想细讲的,但是被学弟学妹们的态度感动了,所以写了一下这个博客,思想在今天白天已经讲过了,所以直接上代码。

           首先,带权并查集必备知识是向量加减规则,不熟悉的可以看我的另外一篇博客(点我

      先放图,模拟的是  x吃y  和x和y同类的向量合并。

          这应该是最难的地方,很多东西白天已经讲过了,具体看代码,我写了比较详细的注释。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxn=50010;
    int p=300000;
    //p%3==0  由于下面有向量相减  可能部分value是负的,所以加上一个比较大的数字变成正数 
    int fa[maxn],n,k,ans,type,x,y,value[maxn];
    //value数组  永远记录的都是   当前节点  到fa[x]的权值  此时fa[x]对应的value不一定更新了 ,需要find进行路径合并 
    //记住  find的功能是找爸爸 + 路径合并 + 更新value[x] 
    //      baba函数的功能是    联合  向量规则更新value 
    //  x->y的权值是1,就是x吃y 
    int find(int x)
    {
        if(x==fa[x])return fa[x]; 
        int tep=fa[x];            //先保存当前的还没有路径合并的父节点 
        fa[x]=find(fa[x]);        //把 父节点权值信息更新 
        value[x]+=value[tep];      //value存的是x到之前的父节点的信息,现在加上 原父节点(tep)合并路径后的权值 
        return fa[x];
    }
    void baba(int x,int y,int type)
    {
        int fx=find(x),fy=find(y);
        if(type==1)         //平级权值为0 
        {
            fa[fx]=fy;
            value[fx]=-value[x]+value[y]+0;  //x的爸爸认y的爸爸当爸爸,用向量规则进行加减 
        }else{              //x吃y  权值1 
            fa[fx]=fy;
            value[fx]=-value[x]+value[y]+1; //x的爸爸认y的爸爸当爸爸,用向量规则进行加减 
        }
    }
    int main(){
        cin>>n>>k;
        for(int i=1;i<=n;i++)
        {
            fa[i]=i;
        }
        while(k--)
        {
            scanf("%d%d%d",&type,&x,&y);
            if(x>n||y>n||(x==y&&type==2)){   //如果标号大于n  或者自己吃自己  肯定错 
                ans++;
                continue;
            }
            if(find(x)!=find(y))             //如果父亲不同 不在同一集合  肯定不会错  现在合并(因为现在给出的信息已经是限制条件了) 
            {
                baba(x,y,type);             //合并的类型是type 
            }else{
                if(type==1)                  //如果是平级的 
                {
                    if((value[x]+p)%3!=(value[y]+p)%3){    //距离根节点的权值  取余3相等才合法(也就是和根节点的相食关系一致) 
                        ans++;                //不合法  加加 
                    }
                }else{
                    if((value[x]-value[y]+p)%3==1||(value[y]-value[x]+p)%3==2){
                        //合法就是x吃y,所以要么x比y大1,要么y比x大2(石头剪子布) 
                    }else{
                        ans++;
                    }
                }
            }
        } 
        cout<<ans<<endl; 
    }
  • 相关阅读:
    JavaScript监听、设置全部ajax访问属性获取返回值(状态码)
    如何在Vue项目中使用vw实现移动端适配
    git 常用命令金字教程
    移动web开发之像素和DPR详解
    小程序-微信开发者工具使用
    小程序开发框架:Taro(一)基础篇
    vscode代码自动补全失效
    JS、C#编码解码
    PHP网页缓存技术
    ajaxfileupload回到json带<pre>
  • 原文地址:https://www.cnblogs.com/mountaink/p/10280170.html
Copyright © 2020-2023  润新知