做这个题的时候想到了可以用前缀的方法,但是没有想到为什么可以用并查集,后来搜到加权并查集,有点懵,然后想了会儿为什么可以这么写,首先之所以发生冲突是因为前面的区间或者通过前面区间可以推出来的新区间与询问的区间有冲突,所以当我们以某个数即某个节点当作根节点的时候,开个dist数组表示i到其根节点的距离,这是便可以想到用并查集做了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 2e5+5;
int n,m,f[maxn],dis[maxn],ans;
void Init();
int Find(int x);
void Union(int x,int y,int s);
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
Init();
for(int i=0;i<m;i++){
int a,b,s;
scanf("%d%d%d",&a,&b,&s);
Union(a-1,b,s);
}
printf("%d\n",ans);
}
}
void Init(){
ans=0;
memset(dis,0,sizeof(dis));
for(int i=0;i<=n;i++){
f[i]=i;
}
}
int Find(int x){
if(x==f[x]){
return x;
}else{
int t=f[x];
f[x]=Find(f[x]);
dis[x]=dis[x]+dis[t];
return f[x];
}
}
void Union(int x,int y,int s){
int f1=Find(x),f2=Find(y);
if(f1==f2){
if(dis[y]!=dis[x]+s){
ans++;
}
}else{
f[f2]=f1;
dis[f2]=dis[x]+s-dis[y];
}
}