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

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

 

 

 

 

P2024 [NOI2001] 食物链 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

// 带权并查集
#include <iostream>
using namespace std;

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

int find(int x){
  if(p[x]==x) return x;
  int t=find(p[x]);  //记录新根t
  d[x]=d[x]+d[p[x]]; //先更新x到新根t的距离
  return p[x]=t;     //再更新p[x],路径压缩
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1; i<=n; i++) p[i]=i;
  while(m--){
    scanf("%d%d%d",&k,&x,&y);
    int px=find(x),py=find(y);
    if(x>n||y>n) ans++;
    else if(k==1){ //x,y是同类情况
      //x,y在同一颗树且不在同一层,则不是同类,是假话
      if(px==py&&((d[x]-d[y])%3+3)%3!=0) ans++;
      //x,y不在同一颗树,则合并集合
      if(px!=py){ 
        p[px]=py; //px指向py
        d[px]=d[y]-d[x]; 
        //x,y应在同一层,到根的距离应相等,d[px]+d[x]=d[y]
      }
    }
    else{ //x吃y情况
      //x,y在同一颗树且x不在y的下一层,则不满足x吃y,是假话
      if(px==py&&((d[x]-d[y])%3+3)%3!=1) ans++;
      //x,y不在同一颗树,则合并集合
      if(px!=py){
        p[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  董晓  阅读(310)  评论(1编辑  收藏  举报