zoukankan      html  css  js  c++  java
  • 食物链

    食物链
    Time Limit: 1000MS Memory Limit: 10000K
    Total Submissions: 53613 Accepted: 15721

    Description
    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。
    现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。
    有人用两种说法对这N个动物所构成的食物链关系进行描述:
    第一种说法是”1 X Y”,表示X和Y是同类。
    第二种说法是”2 X Y”,表示X吃Y。
    此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
    1) 当前的话与前面的某些真的话冲突,就是假话;
    2) 当前的话中X或Y比N大,就是假话;
    3) 当前的话表示X吃X,就是假话。
    你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。

    Input
    第一行是两个整数N和K,以一个空格分隔。
    以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
    若D=1,则表示X和Y是同类。
    若D=2,则表示X吃Y。

    Output
    只有一个整数,表示假话的数目。

    Sample Input

    100 7
    1 101 1
    2 1 2
    2 2 3
    2 3 3
    1 1 3
    2 3 1
    1 5 5

    Sample Output

    3

    Source
    Noi 01
    并查集带权值很好的例题
    大神的题解,讲的很详细

    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <stdio.h>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    
    const int MAX = 55000;
    
    int n,k;
    
    struct node
    {
        int parent;
        int relation;
    } pre[MAX];
    
    void init()
    {
        for(int i=0; i<=n; i++)
        {
            pre[i].parent=i;
            pre[i].relation=0;
        }
    }
    
    int Find(int x)//压缩路径
    {
        if(pre[x].parent==x)
        {
            return x;
        }
        int tmp=pre[x].parent;
        pre[x].parent=Find(pre[x].parent);
        pre[x].relation=(pre[tmp].relation+pre[x].relation)%3;//更改节点关系为节点与根节点的关系
        return pre[x].parent;
    }
    void Union(int x,int y,int a,int b,int d)
    {
        pre[b].parent=a;
        pre[b].relation=((3-pre[y].relation)+(d-1)+pre[x].relation)%3;//合并,将两个集合合并成一个集合,通过逆推节点与根节点的关系找到根节点与节点的关系,将新节点与根节点的关系更新
    }
    int main()
    {
        int x,y,d;
        int ans=0;
        scanf("%d %d",&n,&k);
        init();
        for(int i=1; i<=k; i++)
        {
            scanf("%d %d %d",&d,&x,&y);
            if(x>n||y>n)
            {
                ans++;
            }
            else if(x==y&&d==2)
            {
                ans++;
            }
            else
            {
                int a=Find(x);
                int b=Find(y);
                if(a!=b)//如果不在同一个集合,说明是真话,就合并区间
                {
                    Union(x,y,a,b,d);
                }
                else
                {
                    switch(d)
                    {
                    case 1:
                        if(pre[x].relation!=pre[y].relation)//不是同类
                        {
                            ans++;
                        }
                        break;
                    case 2:
                        if((pre[y].relation+3-pre[x].relation)%3!=1)
                        {
                            ans++;
                        }
                    }
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    apache安全—用户访问控制
    hdu 3232 Crossing Rivers 过河(数学期望)
    HDU 5418 Victor and World (可重复走的TSP问题,状压dp)
    UVA 11020 Efficient Solutions (BST,Splay树)
    UVA 11922 Permutation Transformer (Splay树)
    HYSBZ 1208 宠物收养所 (Splay树)
    HYSBZ 1503 郁闷的出纳员 (Splay树)
    HDU 5416 CRB and Tree (技巧)
    HDU 5414 CRB and String (字符串,模拟)
    HDU 5410 CRB and His Birthday (01背包,完全背包,混合)
  • 原文地址:https://www.cnblogs.com/juechen/p/5256006.html
Copyright © 2011-2022 走看看