#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int fa[55555]; //父节点
int ra[55555]; //当前节点与根节点的关系 0为同类 1为父吃子 2为子吃父
void init(int n) { //初始
for(int i=0;i<=n;i++) {
fa[i]=i;
ra[i]=0;
}
}
int find_fa(int n) {
if(n!=fa[n]) {
int tt=fa[n];
fa[n]=find_fa(fa[n]);
ra[n]=(ra[n]+ra[tt])%3;//将当前点的权值根更改为 根节点与父节点
//和 父节点与当前节点的总和 所以父节点的更新一定要先完成
// 所以有保存父节点的tt的必要
}
return fa[n];
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
init(n);
int ans=0;
int d,x,y;
for(int i=1;i<=k;i++) {
scanf("%d%d%d",&d,&x,&y);
if(x>n||y>n) { //第一种情况
ans++;
continue;
}
if(d==2&&x==y) { //第二种情况
ans++;
continue;
}
int fx=find_fa(x); //找第一个节点的根节点
int fy=find_fa(y); //找第二个节点的根节点
if(fx==fy) { //如果两个根节点是同一个
if(d==1&&ra[x]!=ra[y]) { //直接判断两个当前节点的权值是否相同
ans++; //来确认是不是同一类
}
if(d==2&&ra[x]!=(ra[y]+2)%3) { //小小的算一下是不是+2的关系
ans++;
}
}
else {
fa[fy]=fx; //修改根节点的关系
ra[fy]=(ra[x]-ra[y]+3+d-1)%3;//修改根节点的权值 如果d==1则说明x和y的权值相同
//所以ra[x]-ra[y]就是ra[fx]-ra[fy]
//如果d==2则说明x吃y 所以x少y 1;
//所以ra[x]-ra[y]+1==ra[fx]-ra[fy]
//d-1经过归纳可以得出
}
}
cout << ans << endl;
return 0;
}
并查集-poj-1182-食物链-带权值的并查集
最新推荐文章于 2020-06-04 20:41:16 发布