zoukankan      html  css  js  c++  java
  • POJ1182 食物链 并查集

    食物链
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 113794   Accepted: 34597

    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

     
      1 #include <cstdio>
      2 #include <iostream>
      3 
      4 
      5 using namespace std;
      6 
      7 const int max_N=50000+2;
      8 const int max_K=1e5+2;
      9 int N,K;
     10 int T[max_K],X[max_K],Y[max_K];
     11 
     12 // 并查集的实现
     13 // 三个并查集
     14 int par[max_N*3];
     15 int ranks[max_N*3];
     16 
     17 void init(int n)
     18 {
     19     for(int i=0;i<n;++i)
     20     {
     21         par[i]=i;
     22         ranks[i]=0;
     23     }
     24 }
     25 
     26 // 寻找所属的类的编号,并优化路径上的所有点
     27 int finds(int x)
     28 {
     29     if(par[x]==x)
     30     {
     31         return x;
     32     }
     33     else
     34     {
     35         // 路径压缩
     36         return par[x]=finds(par[x]);
     37     }
     38 }
     39 
     40 // 并查集合并操作
     41 void unite(int x,int y)
     42 {
     43     x=finds(x);
     44     y=finds(y);
     45 
     46     if(x==y)
     47     {
     48         return;
     49     }
     50 
     51     // 合并到深度大的那颗树
     52     if(ranks[x]<ranks[y])
     53     {
     54         par[x]=y;
     55     }
     56     else if(ranks[x]==ranks[y])
     57     {
     58         // 随意连边,这边向y连边
     59         par[x]=y;
     60         ++ ranks[y];
     61         //par[y]=x;++ranks[x];
     62     }
     63     else
     64     {
     65         par[y]=x;
     66     }
     67 }
     68 
     69 bool same(int x,int y)
     70 {
     71     return finds(x)==finds(y);
     72 }
     73 
     74 void solve()
     75 {
     76     // 错误信息数
     77     int ans=0;
     78     // 初始化并查集
     79     init(N*3);
     80 
     81     for(int i=0;i<K;++i)
     82     {
     83         int x=X[i]-1;
     84         int y=Y[i]-1;
     85 
     86         if(x<0 || x>=N || y<0 || y>=N)
     87         {
     88             ++ans;
     89             continue;
     90         }
     91 
     92         // X 与 Y 是同一类
     93         if(T[i]==1)
     94         {
     95 
     96             // 冲突的情况
     97             // 1. x吃y
     98             // 2. y吃x
     99             if(same(x,y+N) || same(y+2*N,x))
    100             {
    101                 ++ans;
    102             }
    103             else
    104             {
    105                 unite(x,y);
    106                 unite(x+N,y+N);
    107                 unite(x+2*N,y+2*N);
    108             }
    109         }
    110         // X 吃 Y
    111         else
    112         {
    113 
    114             // 冲突的情况
    115             // 1. x与y同一类
    116             // 2. y吃x
    117             if(same(x,y) || same(y+2*N,x))
    118             {
    119                 ++ans;
    120             }
    121             else
    122             {
    123                 unite(x,y+N);
    124                 unite(x+N,y+2*N);
    125                 unite(x+2*N,y);
    126             }
    127         }
    128     }
    129 
    130 
    131     printf("%d
    ",ans);
    132 }
    133 
    134 int main()
    135 {
    136     scanf("%d %d",&N,&K);
    137     for(int i=0;i<K;++i)
    138     {
    139         scanf("%d %d %d",&T[i],&X[i],&Y[i]);
    140     }
    141 
    142     solve();
    143 
    144     return 0;
    145 }
    146 
    147 
    148 /*
    149 
    150 100 7
    151 1 101 1
    152 2 1 2
    153 2 2 3
    154 2 3 3
    155 1 1 3
    156 2 3 1
    157 1 5 5
    158 */
  • 相关阅读:
    从0系统学Android-2.3使用 Intent 在 Activity 之间穿梭
    从0系统学Android-2.1Activity的使用
    从0系统学Android-1.4日志工具的使用
    从0系统学Android--1.3创建你的第一个 Android 项目
    从0系统学Android--1.2 手把手带你搭建开发环境
    从0系统学 Android--1.1认识 Android
    Android 蓝牙开发(3)——蓝牙的详细介绍
    Android 蓝牙开发(3)——蓝牙的详细介绍
    Android 蓝牙开发(2)——低功耗蓝牙
    Android 蓝牙开发(1)
  • 原文地址:https://www.cnblogs.com/jishuren/p/12304657.html
Copyright © 2011-2022 走看看