思路:实际上也还是一道带权并查集的板子?(虽然wa6),总体思路就是通过两个点到根节点的距离来更新
两个点之间的距离可以由下图来表示 ,然后直接把
更新出来。
但是在更新的时候有一个问题要处理
因为加入两个点的范围都是闭区间,然后我们平常算区间和都是半开半闭的
如:
就比如加入和
这种情况的时候的时候3这个位置会多加一次,那么我们可以让我们的x自减代表左边开区间的情况,那么我们的
就是
,
就是
,那就可以直接通过修改后的区间来进行判断。
代码:
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;
const int N=1000000+100;
int n ,m;
ll h;
int p[N];
ll d[N];
int find(int x)
{
if(p[x]!=x)
{
int t=find(p[x]);
d[x]+=d[p[x]];
p[x]=t;
}
return p[x];
}
int main()
{
int t;
// cin>>n>>m;
while(~scanf("%d%d",&n,&m))
{
for(int i =0;i<=n+1;i++){
p[i]=i;
d[i]=0;
}
int res=0;
while(m--)
{
int x , y;
cin>>x>>y>>h;
x--;
int tx=find(x),ty=find(y);
if(tx!=ty)
{
p[tx]=ty;
d[tx]=h-d[x]+d[y];
}
else if(d[x]-d[y]!=h){
res++;
// cout<<"有问题噢~"<<endl;
}
}
cout<<res<<endl;
}
return 0;
}