zoukankan      html  css  js  c++  java
  • poj 1182 并查集

    并查集是十分有用的数据结果,对于一般人来说,这个应当是十分简单的应用,但是对于我来说却不然。上次比赛的时候有个题目就是因为自己并查集写得有问题而WA了好几次。。。

    1182这道题目的大意是:有ABC三个物种,A吃B,B吃C,C吃A。现在有N个编号的个体(1-N),不知道每个个体分别属于哪个物种。现在有K条语句,每条语句有两种形式:

    1. 1 a b 表示编号为a和b的个体属于同一个物种;
    2. 2 a b表示编号为a的个体吃b;

    这些判断语句不一定全为真。一条判断语句为假的条件是:

    1. a,b大于N;
    2. 2 a a;
    3. 与前矛盾;

    现在的问题是判断到底有多少条语句是假。

    网上看到的解决方法。经典的并查集应用。这个问题的关键,我觉得是应该注意到进食的回环关系,并且在数学上对这个关系进行表示,那就是模运算。建立辅助数组dis[N],表示每个结点到其根节点的距离。dis[i]=0表示该结点和根节点属于同一物种。dis[i]=1该结点物种吃根节点。dis[i]=2表示根结点物种吃该结点。这样每条语句相当于就是在对并查集进行操作了。这里需要注意的是判断和路径压缩。

    先说判断。任意两个已经建立关系的物种应该根结点相同,这样就很容易算出他们的相对距离,从而检查有无矛盾。

    再说路径压缩。也就是新建立关系时应该怎样调整。譬如现在有语句a,x,y。这个a为1或者2。如果此时x,y的根结点不相同,那么他们x到y的距离就应该是a-1。所以x对应的根结点rx到y对应的根结点ry的距离d应该满足:dis[x]+d ==dis[y]+a-1(mod 3)。所以d = (dis[y]-dis[x]+a+2)%3。注意到原来以rx为根的其他节点的dis值应该也要更新。所以getfather过程中进行路径压缩中通知应该更新dis值。

    re

       1: #include <iostream>
       2: #include <cstdio>
       3: #include <cstring>
       4: using namespace std;
       5: const int maxn = 50010;
       6: int dis[maxn],father[maxn];
       7: int sum;
       8: int getfather(int u)
       9: {
      10:     int s;
      11:     if(father[u] == u) return u;
      12:     else s = getfather(father[u]);
      13:     dis[u] = (dis[u]+dis[father[u]])%3;
      14:     father[u] = s;
      15:     return s;
      16: }
      17: int main()
      18: {
      19:     //freopen("test.txt","r",stdin);
      20:     int n,k,a,x,y,fx,fy,d;
      21:     scanf("%d%d",&n,&k);
      22:     memset(dis,0,sizeof(dis));
      23:     for(int i=0;i<n;++i)
      24:         father[i] = i;
      25:     sum = 0;
      26:     for(int i=0;i<k;++i)
      27:     {
      28:         scanf("%d%d%d",&a,&x,&y);
      29:         fx = getfather(x);
      30:         fy = getfather(y);
      31:         if(x>n || y>n || (a==2 && x==y))
      32:         {
      33:             sum++;
      34:             continue;
      35:         }
      36:         else if(fx == fy)
      37:         {
      38:             if(a==1 && dis[x] != dis[y])
      39:             {sum++;continue;}
      40:             else if(a==2 && (dis[x]-dis[y]+3)%3!=1)
      41:             {sum++;continue;}
      42:         }
      43:         else if(fx != fy)
      44:         {
      45:             d = (a+2+dis[y]-dis[x])%3;
      46:             dis[fx] = d;
      47:             father[fx] = fy; 
      48:         }
      49:  
      50:     }
      51:     printf("%d\n",sum);
      52: }
  • 相关阅读:
    HDU5446 Unknown Treasure
    C语言课设——通讯录操作系统
    判断设备是否横屏
    禁止用户横屏
    用javascript编写ps脚本
    用户鼠标指针的样式
    如何使用typescript开发node(自动编译,自动重启)
    CSS3:box-sizing:不再为匣子模型而烦恼
    命令行开启自动编译scss(webstrom可开启自动编译)
    TypeError: Cannot read property 'replace' of undefined ----angular2
  • 原文地址:https://www.cnblogs.com/bovine/p/2432702.html
Copyright © 2011-2022 走看看