• 食物链 noj207


    #include<stdio.h>
    int fa[50005]={0};
    int rank[50005]={0};
    int n;
    void initial()
    {
        for(int i=1;i<=n;i++)
        {
            fa[i]=i; rank[i]=0;
        }
    }
    int getfather(int x)
    {
        if(x==fa[x])  return x;
        int oldfa = fa[x];
        fa[x]=getfather(fa[x]);
        rank[x]=(rank[x]+rank[oldfa])%3;  //用向量的形式很快就可以看出来
        return fa[x];
    }
    void unionset(int r,int x,int y)
    {
        int fx,fy;
        fx=getfather(x); fy=getfather(y);
        if(fx==fy) return;
        fa[fx]=fy;
        rank[fx]=(rank[y]+r-rank[x]+3)%3;   // 这里同样可以用向量来推公式。另外需要注意的是,这里只更新了fx的rank值,而fx的儿子的rank值都没有更新会不会有问题。其实不碍事,由于我们每次输入一组数据我们都对x和y进行了getfather的操作(x>n || y>n ……)的除外。在执行getfather的操作时,在回溯的过程中就会把fx的儿子的rank值都更新了。
        return ;
    }
    int istrue(int d,int x,int y)
    {
        int fx,fy,r;
        if(x>n || y>n || ((x==y)&&(d==2)) )
            return 0;
        fx=getfather(x); fy=getfather(y);
        if(fx!=fy)  return 1;
        else
        {
            if(rank[x]==((d-1)+rank[y])%3) return 1;  // 这个公式可以用向量来推:如果( f(x,y) + f(y,father[y]))% 3 == f(x,father[x]) 则是正确的,否则是错的。这个形式可以用向量来表示,就是判断这个向量加法对不对   x--->y + y---> fx(fy) 是否等于  x--->fx(fy)
            else  return 0;
        }
    }
    int main()
    {
        int k,i,x,y,d; int ans=0;
        scanf("%d%d",&n,&k);
        initial();
        for(i=1;i<=k;i++)
        {
            scanf("%d%d%d",&d,&x,&y);
            if( !istrue(d,x,y) )
                ans++;
            else
                unionset(d-1,x,y);
        }
        printf("%d\n",ans);
        return 0;
    }
    

    对于rank[]的值用向量求,不明白,有懂的给讲解一下!谢谢啦!

  • 相关阅读:
    lumen简单使用exel组件
    VIM 批量注释的两种方法 (转)
    linux时间校准 设置时间为上海时区
    lumen发送邮件配置
    centos 下安装redis 通过shell脚本
    shell 脚本接收参数
    linux设置系统变量
    linux通配符
    UCCI协议[转]
    一种编程范式:对拍编程
  • 原文地址:https://www.cnblogs.com/yaling/p/2956506.html
Copyright © 2020-2023  润新知