题目
有未知的(n)个数,有(m)组询问,形如区间和等于给定值,
问有多少条错误的询问,一旦错误忽略此条询问
(nleq 2*10^5,mleq 4*10^4)
分析
用带权并查集,记录每个点到根节点的和,即是在合并时
(s[y']=s[x]+w-s[y]),表示(y')到(x')的距离,
通过(x'<x,y'<y)推出,如果两个点已经合并那么判断(s[y]-s[x]=w)
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=200011;
int n,f[N],ans,s[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline signed getf(int u){
if (f[u]==u) return u;
rr int F=getf(f[u]);
s[u]+=s[f[u]];
return f[u]=F;
}
signed main(){
for (rr int i=0;i<N;++i) f[i]=i;
while (scanf("%d",&n)==1){
for (rr int T=iut();T;--T){
rr int x=iut()-1,y=iut(),w=iut();
rr int fa=getf(x),fb=getf(y);
if (fa!=fb) f[fb]=fa,s[fb]=s[x]+w-s[y];
else if (w!=s[y]-s[x]) ++ans;
}
printf("%d
",ans);
for (rr int i=0;i<=n;++i) f[i]=i,s[i]=0; ans=0;
}
return 0;
}