看大佬的博客理解了,疑问的地方有两点,一:程序中的距离转换怎么用和根节点的距离来解释?
二:合并时为什么a--或者b++?直接合并a,b不行吗?这个问题我已经理解了,下面是我的思路:
问题一的思路如图:程序中a,b,x,y四个节点之间距离关系的转换
问题二: 为什么不能在unions()函数中直接传入a和b?答案是不能的:需要a--或b++
最后,注意程序的连续输入:while(cin>>a>>b)
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=200005;
int pre[maxn];
int sum[maxn];
int n,m;
int cnt;
void init()
{
memset(sum,0,sizeof(sum));
for(int i=0; i<=n+3; i++)
{
pre[i]=i;
}
cnt=0;
}
int finds(int x)
{
if(x==pre[x])
return x;
int t=pre[x];
pre[x]=finds(pre[x]);
sum[x]+=sum[t];//增加量sum[t]是从根节点到当前节点路径上权值之和
return pre[x];
}
void unions(int a,int b,int s)
{
int x=finds(a);
int y=finds(b);
if(x==y)
{
if(sum[a]+s!=sum[b])
cnt++;
return;
}
else if(x<y)
{
pre[y]=x;//将前面点的根节点作为合并之后的根节点
sum[y]=sum[a]+s-sum[b];
}
else//x>y
{
pre[x]=y;
sum[x]=sum[b]-sum[a]-s;
}
}
int main()
{
int a,b,s;//有可能是没有连续输入的原因
while(cin>>n>>m)
{
init();
for(int i=0; i<m; i++)
{
cin>>a>>b>>s;
unions(a-1,b,s);
}
cout<<cnt<<endl;
}
return 0;
}