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

    食物链

    Time Limit: 1000MS

     

    Memory Limit: 10000K

    Total Submissions: 55260

     

    Accepted: 16210

    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

    【思路】

      并查集。

        1、 i-x表示i属于x种类,一个节点分别有i-A,i-B,i-C表示i属于的种类。

        2、 并查集里的所有元素表示同时发生。

      冲突:w==1但u吃v或v吃u,w==2但uv同组或v吃u。

      合并:w==1则合并u-x,v-x,w==2则合并u-A,v-B 和 u-B,v-C 和u-C,v-A

    (以上思路源于《挑战程序设计》)

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 
     5 const int maxn = 150000+10;
     6 
     7 int p[maxn];
     8 int n,m;
     9 
    10 int find(int x) {
    11     return x==p[x]?x:p[x]=find(p[x]);
    12 }
    13 bool same(int x,int y) {
    14     return find(x)==find(y); 
    15 }
    16 void unite(int x,int y) {
    17     p[find(x)]=find(y);
    18 }
    19 void init(int N) {
    20     for(int i=0;i<N;i++) p[i]=i;
    21 }
    22 
    23 int main() {
    24     scanf("%d%d",&n,&m);
    25     init(3*n);
    26     int u,v,w,ans=0;
    27     for(int i=0;i<m;i++) {
    28         scanf("%d%d%d",&w,&u,&v);
    29         u--; v--;
    30         if(u<0||u>=n||v<0||v>=n) {
    31             ans++;
    32             continue;
    33         }
    34         if(w==1) {
    35             if(same(u,v+n) || same(u,v+2*n)) { //u吃v 或 v吃u 
    36                 ans++;
    37                 continue;
    38             }
    39             else {
    40                 unite(u,v);
    41                 unite(u+n,v+n);
    42                 unite(u+2*n,v+2*n);
    43             }
    44         }
    45         else {
    46             if(same(u,v) || same(u,v+2*n)) {
    47                 ans++;
    48                 continue;
    49             }
    50             else {
    51                 unite(u,v+n);
    52                 unite(u+n,v+2*n);
    53                 unite(u+2*n,v);
    54             }
    55         }
    56     }
    57     printf("%d
    ",ans);
    58     return 0;
    59 }
  • 相关阅读:
    【转】Android中设置TextView的颜色setTextColor
    【转】android颜色对应的xml配置值
    【转】color颜色十六进制编码大全
    【转】Usage of sendBroadcast()
    【转】Android4.3 蓝牙BLE初步
    【转】android中重复连接ble设备导致的连接后直接返回STATE_DISCONNECTED的解决办法---不错不错,重新连接需要花费很长的时间
    【转】推荐--《Android深入浅出》----不错
    【转】google chrome如何设置主页
    【转】Chrome保存mhtml网页文件的方法 – 无需任何插件,完美!
    【转】Android--广播BroadcastReceiver
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4934207.html
Copyright © 2011-2022 走看看