How Many Answers Are Wrong
原题链接https://vjudge.net/contest/350427#problem/D
本题为带权并查集 ,给你两个点之间的距离,然后推出下一条是否正确,
题目的.重点在于如何对并查集进行合并,关于权值的计算。
本题计算时我使用的方法可以理解为坐标轴的计算,
全部合并到较小的数上去,也就是以最小的值为根
对于样例而言
先将1跟10链接
通过权值的关系我们可以计算出每个点到达0点的关系(将所有区间的左区间减一位变为开区间),
0~3:32
0~6:100-28=72;
0~10:100;
在我们得到4~6之后,显然3-6这个区间两边的端点都有根,并且根相同,权值便可以直接计算,为6的权值减去3的权值,然后和题目给出的值进行计算,判断是否相同
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<fstream>
#include<queue>
using namespace std;
long long pre[300005];
long long rank1[300005];
long long find(long long x)
{
if(x==pre[x])
{
return x;
}
long long t=pre[x];
pre[x]=find(pre[x]);
rank1[x]+=rank1[t];
return pre[x];
}
void join(long long x,long long y,long long a,long long b,long long c)
{
if(x>y)//对于根的不同大小进行合并,具体有公式就根据坐标轴推出即可
{
pre[y]=x;
rank1[y]=rank1[a]-rank1[b]-c;
}
else
{
pre[x]=y;
rank1[x]=rank1[b]-rank1[a]+c;
}
}
int main()
{
long long n,m;
while(~scanf("%lld %lld",&n,&m))
{
long long i,j;
memset(rank1,0,sizeof(rank1));
for(i=0; i<=200001; i++)
{
pre[i]=i;
}
long long sum1,sum2,sum3;
long long sum=0;
while(m--)
{
scanf("%lld %lld %lld",&sum1,&sum2,&sum3);
sum1--;
long long ss1=find(sum1);
long long ss2=find(sum2);
if(ss1==ss2&&rank1[sum1]!=rank1[sum2]+sum3)//根相同说明已经连接起来,可以判断,进行判断
{
sum++;
}
else if(ss1!=ss2)
{
join(ss1,ss2,sum1,sum2,sum3);//两个不同的集合进行合并。
}
}
printf("%lld\n",sum);
}
return 0;
}