#带权并查集#HDU 3038 How Many Answers Are Wrong
题目
有未知的\(n\)个数,有\(m\)组询问,形如区间和等于给定值,
问有多少条错误的询问,一旦错误忽略此条询问
\(n\leq 2*10^5,m\leq 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\n",ans);
		for (rr int i=0;i<=n;++i) f[i]=i,s[i]=0; ans=0;
	}
	return 0;
}

                
            
        
浙公网安备 33010602011771号