C125【模板】带权并查集 P2024 [NOI2001] 食物链

C125【模板】带权并查集 P2024 [NOI2001] 食物链_哔哩哔哩_bilibili

 

P2024 [NOI2001] 食物链 - 洛谷

// 带权并查集
#include<bits/stdc++.h>
using namespace std;

const int N=50005;
int n,k,ans;
int fa[N],d[N]; //d[x]表示x到根的距离

int find(int x){
  if(fa[x]==x) return x;
  int t=find(fa[x]);  //记录新根t
  d[x]=d[x]+d[fa[x]]; //先更新x到新根t的距离
  return fa[x]=t;     //再更新fa[x],路径压缩
}
int main(){
  scanf("%d%d",&n,&k);
  for(int i=1; i<=n; i++) fa[i]=i;
  for(int op,x,y;k--;){
    scanf("%d%d%d",&op,&x,&y);
    int px=find(x),py=find(y);
    if(x>n||y>n) ans++;
    else if(op==1){ //x,y是同类
      if(px==py&&((d[x]-d[y])%3+3)%3!=0) ans++; //x,y在同一颗树且不在同一层,则不是同类,是假话
      if(px!=py){ //x,y不在同一颗树,则合并集合
        fa[px]=py; //px指向py
        d[px]=d[y]-d[x]; //x,y应在同一层,到根的距离应相等,d[px]+d[x]=d[y]
      }
    }
    else{ //x吃y
      if(px==py&&((d[x]-d[y])%3+3)%3!=1) ans++; //x,y在同一颗树且x不在y的下一层,则不满足x吃y,是假话
      if(px!=py){ //x,y不在同一颗树,则合并集合
        fa[px]=py; //px指向py
        d[px]=d[y]+1-d[x]; //x应在y的下一层,到根的距离应多1,d[px]+d[x]=d[y]+1
      }        
    }
  }
  printf("%d\n",ans);
}

 

posted @ 2024-05-24 17:41  董晓  阅读(1030)  评论(1)    收藏  举报