zoukankan      html  css  js  c++  java
  • 又见关系并查集 以POJ 1182 食物链为例

    简单的关系并查集一般非常easy依据给出的关系搞出一个有向的环,那么两者之间的关系就变成了两者之间的距离。

    对于此题:

    若u。v不在一个集合内,则显然此条语句会合法(暂且忽略后两条。下同)。

    那么将fu 变为 fv的儿子时需加一条权值为 w 的边,w 满足(w + ru)%3 = (rv+ (D == 1?

    0 : 1))%3(ru。rv分别为u,v与fv的关系,即距离)。

    之所以在D == 2时加 1。是由于u吃v表明着u到fv的距离比v到fv的距离大1。

    同理。D == 1时,表明两者到fv的距离应该相等。

    若u,v在一个集合内。仅仅须要推断ru%3 == (rv+(D == 1?):1))%3 是否成马上可。

    只是这个题数据略坑啊。写成多组输入的根本过不了。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <map>
    
    #pragma comment(linker, "/STACK:1024000000");
    #define EPS (1e-8)
    #define LL long long
    #define ULL unsigned long long
    #define _LL __int64
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    struct N
    {
        int fa,re;
    } st[50010];
    
    int Find(int x,int &R)
    {
        int f,re = 0;
    
        f = x;
    
        while(f != st[f].fa)
        {
            re = (re+st[f].re)%3;
            f = st[f].fa;
        }
    
        R = re;
        int tre = 0,temp,tf;
    
        while(x != st[x].fa)
        {
            tf = st[x].fa;
            temp = st[x].re;
            
            st[x].re = (re-tre+3)%3;
    
            tre = (tre+temp)%3;
            st[x].fa = f;
            x = tf;
        }
    
        return f;
    }
    
    bool Merge(int w,int u,int v)
    {
        int ru,rv;
        int fu = Find(u,ru);
        int fv = Find(v,rv);
    
        if(fu != fv)
        {
            st[fu].fa = fv;
            if(w == 2)
                st[fu].re = ((rv+1)%3 - ru + 3)%3;
            else
                st[fu].re = (rv%3- ru + 3)%3;
        }
        else
        {
            if(w == 1 && ru != rv)
                return false;
    
            if(w == 2 && ru != (rv+1)%3 )
                return false;
        }
    
        return true;
    }
    
    int main()
    {
        int n,k;
    
        int i,j,u,v,w;
    
        scanf("%d %d",&n,&k);
        {
            for(i = 1; i <= n; ++i)
                st[i].fa = i,st[i].re = 0;
    
            int ans = 0;
    
            while(k--)
            {
                scanf("%d %d %d",&w,&u,&v);
    
                if(u > n || v > n || (w == 2 && u == v))
                {
                    ans++;
                    continue;
                }
    
                if(Merge(w,u,v) == false)
                {
                    ans++;
                }
            }
    
            printf("%d
    ",ans);
        }
    
        return 0;
    }

  • 相关阅读:
    LeetCode#160-Intersection of Two Linked Lists-相交链表
    LeetCode#2-Add Two Numbers-两数相加
    LeetCode#141-Linked List Cycle-环形链表
    LeetCode#66-Plus One-加一
    LeetCode#35-Search Insert Position-搜索插入位置
    LeetCode#203-Remove Linked List Elements-移除链表元素
    基姆拉尔森公式
    [leetcode] 树(Ⅲ)
    常用算法合集(一)
    离散数学 II(最全面的知识点汇总)
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7059388.html
Copyright © 2011-2022 走看看