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

    动物王国中有三类动物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
     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 using namespace std;
    10 const int MAX=5e4+5;
    11 int par[MAX*3],rankk[MAX*3];
    12 void init(int n)
    13 {
    14     for(int i=0;i<n;i++)
    15     {
    16         par[i]=i;
    17         rankk[i]=0;
    18     }
    19 }
    20 int find(int x)
    21 {
    22     if(par[x]==x)
    23         return x;
    24     else
    25         return par[x]=find(par[x]);
    26 }
    27 void unite(int x,int y)
    28 {
    29     x=find(x);
    30     y=find(y);
    31     if(x==y)
    32         return;
    33     if(rankk[x]<rankk[y])
    34         par[x]=y;
    35     else
    36     {
    37         par[y]=x;
    38         if(rankk[x]==rankk[y])
    39             rankk[x]++;
    40     }
    41 }
    42 bool same(int x,int y)
    43 {
    44     return find(x)==find(y);
    45 }
    46 int n,k;
    47 int an;
    48 int opt,a,b;
    49 int main()
    50 {
    51     scanf("%d%d",&n,&k);
    52     init(3*n);
    53     while(k--)
    54     {
    55         scanf("%d%d%d",&opt,&a,&b);
    56         a--;b--;
    57         if(a<0||b<0||a>=n||b>=n||(opt==2&&a==b))
    58         {
    59             an++;continue;
    60         }
    61         if(opt==1)
    62         {
    63             if(same(a,b+2*n)||same(a+2*n,b))
    64             {
    65                 an++;
    66                 continue;
    67             }
    68             else
    69             {
    70                 unite(a,b);
    71                 unite(a+n,b+n);
    72                 unite(a+2*n,b+2*n);
    73             }
    74         }
    75         else
    76         {
    77             if(same(a,b)||same(a,b+2*n))
    78             {
    79                 an++;continue;
    80             }
    81             else
    82             {
    83                 unite(a+2*n,b);
    84                 unite(a+n,b+2*n);
    85                 unite(a,b+n);
    86             }
    87         }
    88     }
    89     printf("%d
    ",an);
    90 }

    用x,x+n,x+2*n,分别表示元素在A、B、C集合中。某两个元素在同一个树中意味他们同时发生或同时不发生。向并查集中加入元素时要把各种情况全部加入,查询是否合法时只需查询1种不行的即可(指吃与被吃的关系)

    2017.7.23重写版

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <queue>
     8 #include <set>
     9 #include <map>
    10 #include <list>
    11 #include <vector>
    12 #include <stack>
    13 #define mp make_pair
    14 //#define P make_pair
    15 #define MIN(a,b) (a>b?b:a)
    16 //#define MAX(a,b) (a>b?a:b)
    17 typedef long long ll;
    18 typedef unsigned long long ull;
    19 const int MAX=2e5+5;
    20 const int INF=1e8+5;
    21 using namespace std;
    22 //const int MOD=1e9+7;
    23 typedef pair<ll,int> pii;
    24 const double eps=0.00000001;
    25 int par[MAX];
    26 int n,k,cnt;
    27 void init(int x)
    28 {
    29     for(int i=0;i<=3*x;i++)
    30         par[i]=i;
    31 }
    32 int find(int x)
    33 {
    34     if(par[x]==x)
    35         return x;
    36     else
    37         return par[x]=find(par[x]);
    38 }
    39 bool same(int x,int y)
    40 {
    41     x=find(x);y=find(y);
    42     return x==y;
    43 }
    44 void unite(int x,int y)
    45 {
    46     x=find(x);y=find(y);
    47     par[x]=y;
    48 }
    49 bool x_eat_y(int x,int y)
    50 {
    51     return same(x,y+n)||same(x+n,y+2*n)||same(x+2*n,y);
    52 }
    53 int d,x,y;
    54 int main()
    55 {
    56     scanf("%d%d",&n,&k);
    57     init(n);
    58     for(int i=1;i<=k;i++)
    59     {
    60         scanf("%d%d%d",&d,&x,&y);
    61         if(x>n||y>n)
    62         {
    63             ++cnt;continue;
    64         }
    65         else
    66         {
    67             if(d==1)
    68             {
    69                 if(x_eat_y(x,y)||x_eat_y(y,x))
    70                 {
    71                     ++cnt;continue;
    72                 }
    73                 else
    74                 {
    75                     unite(x,y);unite(x+n,y+n);unite(x+2*n,y+2*n);
    76                 }
    77             }
    78             else
    79             {
    80                 if(x==y||same(x,y)||same(x+n,y+n)||same(x+2*n,y+2*n)||x_eat_y(y,x))
    81                 {
    82                     ++cnt;continue;
    83                 }
    84                 else
    85                 {
    86                     unite(x,y+n);unite(x+n,y+2*n);unite(x+2*n,y);
    87                 }
    88             }
    89         }
    90     }
    91     printf("%d
    ",cnt);
    92     return 0;
    93 }
  • 相关阅读:
    python字典实现原理-哈希函数-解决哈希冲突方法
    ElasticSearch-倒排索引
    ElasticSearch-核心概念
    MarkdownPad2基础语法
    下载python3.6,进行编译安装,运行django程序
    linux-指令1
    注解和反射
    Htlm和Css
    JAVASE加强
    网络编程
  • 原文地址:https://www.cnblogs.com/quintessence/p/6572598.html
Copyright © 2011-2022 走看看