zoukankan      html  css  js  c++  java
  • 带权并查集--P2024 [NOI2001]食物链

    因为我们一共有三个群体,所以我们可以开三倍的并查集,$1$~$n$的部分表示为A的群体,$n+1$~$2n$的部分表示B的群体,$2n+1$~$3n$的部分表示C的群体

    题干给的三种关系,A吃B,B吃C,C吃A

    我们可以由二倍并查集,由特殊到一般,由二到三,在二倍并查集中:当A中的x与B中的y合并,有关系x吃y,当C中的x与C中的y合并,有关系x和y是同类。那么在三倍并查集中就有这样的几种关系:

    udpate(x,y) | update(x+n,y+n) | update(x+n+n,y+n+n)表示着同类合并

    find(x)==find(y+n)表示x吃y同理可得剩下的情况(主要是因为我懒)

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 using namespace std;
     5 int n,k;
     6 const int maxn=1e5+10;
     7 int mark,x,y;
     8 int ans,fa[3*maxn];
     9 void init(){
    10   for (int i = 1;i <= n*3;i++) fa[i]=i;
    11 }
    12 int find(int x){
    13   if (fa[x]==x) return x;
    14   else return fa[x]=find(fa[x]);
    15 }
    16 void update(int x,int y){
    17   int fx=find(x),fy=find(y);
    18   fa[fx]=fy;
    19 }
    20 int main(){
    21   scanf("%d%d",&n,&k);
    22   init();
    23   for (int i = 1;i <= k;i++){
    24     scanf ("%d%d%d",&mark,&x,&y);
    25     if (x>n||y>n){ans++; continue;}
    26     if (mark==1){
    27       if (find(x)==find(y+n)||find(x+n)==find(y)) ans++;
    28       else {
    29     update(x,y);
    30     update(x+n,y+n);
    31     update(x+n+n,y+n+n);
    32       }
    33     }
    34     else{
    35       if (find(x)==find(y)||find(x+n)==find(y)) ans++;
    36       else {
    37     update(x,y+n);
    38     update(x+n,y+n+n);
    39     update(x+n+n,y);
    40       }
    41     }
    42   }
    43   printf("%d
    ",ans);
    44   return 0;
    45 }
  • 相关阅读:
    Android 锁屏消息调研
    [GODOT]可复用移动组件(载具类)
    [GODOT]技能系统初探
    [GODOT]获取节点
    美丽的秋天
    生活
    day7.17
    html
    day 2015.6.08
    不会转载只能先留下网址了
  • 原文地址:https://www.cnblogs.com/very-beginning/p/13716164.html
Copyright © 2011-2022 走看看