zoukankan      html  css  js  c++  java
  • poj1182食物链(种类并查集)

    链接:http://poj.org/problem?id=1182

    并查集维护的是一种相对关系;

    而要解决敌人的敌人是朋友(也就是循环对称)的这种关系,用种类并查集来解决

    如果是三个及以上的集合,只要每个集合都是等价的,且集合间的每个关系都是等价的,就能够用种类并查集进行维护。

    题意:

     

     观察下,(普通并查集做法)发现三个集合可以用种类并查集来解决:可以用一个三倍大小的并查集进行维护,用i+n表示i的捕食对象,而i+2n表示i的天敌。

    (带权并查集做法)带权并查集的权值表示两个动物在食物链上的相对关系A->B=0(同类),A->B=1(A吃B),A->B=2(B吃A);

    注意三个点:

    1,路径压缩时,如何更新value值:

    A->B为1,B->C为1,怎么求A->C?显然A吃B,B吃C,那么C应该吃A,A->C应该为2;

    A->B为2,B->C为2,怎么求A->C?显然B吃A,C吃B,那么A应该吃C,A->C应该为1;

    A->B为0,B->C为1,怎么求A->C?显然A、B同类,那么A应该吃C,A->C应该为1;

    观察可发现规律:A->C = (A->B + B->C) % 3;

    向量:(A->B=AB=1,B->C=BC=1   =>   A->C=AC=2)

    2,区间合并时,如何更新value值:

    普通的带权合并上加个取模即可,va[fx]=(s+va[y]-va[x])%3;

    3,如何判断是否矛盾

    为了防止负数的影响 A->B=(A->C - B->C + 3) % 3,将A->B与题中给定的值判断即可

    因为题中只有1和2的情况,所以--d;

    代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define maxx 1010
    #define maxn 50010
    int fa[maxn],va[maxn];
    int Find(int x)
    {
        if(x!=fa[x])
        {
            int t=fa[x];
            fa[x]=Find(fa[x]);
            va[x]=(va[x]+va[t])%3;//合并权值
        }
        return fa[x];
    }
    void Union(int x,int y,int s)
    {
        int fx=Find(x);
        int fy=Find(y);
        if(fx!=fy)
        {
            fa[fx]=fy;
            va[fx]=s+va[y]-va[x];
        }
    }
    int main()
    {
        for(int i=0; i<=maxn-10; i++)
             fa[i]=i;
        int n,k;
        cin>>n>>k;
        int ans=0;
        while(k--)
        {
            int d,x,y;
            cin>>d>>x>>y;
            if((x==y&&d==2)||x>n||y>n)
                ans++;
            else
            {
                int fx=Find(x),fy=Find(y);
                if(fx==fy)
                {
                    if((d-1)!=(va[x]-va[y]+3)%3)
                        ans++;
                }
                else
                {
                    fa[fx]=fy;
                    va[fx]=((d-1)+va[y]-va[x])%3;
                }
            }
        }
        cout<<ans<<endl;
        return 0;}
  • 相关阅读:
    iOS:抽屉侧滑动画两种形式(1、UIView侧滑 2、ViewController侧滑)
    深入浅出 React Native:使用 JavaScript 构建原生应用
    JQuery:通过noConflict()方法同时使用jQuery 和其他框架
    JQuery AJAX: 了解jQuery AJAX
    iOS:iOS开发非常全的三方库、插件等等
    JavaScript:实现瀑布流
    iOS:crash崩溃日志分析
    敏捷开发一千零一夜
    江恩交易战法
    苹果:贩卖高科技的美学体验
  • 原文地址:https://www.cnblogs.com/sweetlittlebaby/p/12654817.html
Copyright © 2011-2022 走看看