具体学习参考https://blog.csdn.net/sunmaoxiang/article/details/80959300#commentBox
这篇博客也是我觉得比较好理解的方法——向量法,具体体现在代码。
hdu 3038 区间和悖论问题
假如说区间【fx,x】是之前建立的区间,他们之间和为sum[x],fx和x的联系可以用集合来存储,同理【fy,y】也是如此。当给出了一个新的区间【x,y】时,且区间和为s。就产生了两种情况了,如果fx == fy 那么这两个区间是有关联的区间,也就是【x,y】之间的和是可以求出的。可以把这个图看成一个向量。 区间【x,y】的和就是可以写成sum[x] - sum[y]。判断给出的s与向量法计算的区间和是否相等就可以判断是否是悖论。
当然如果fx != fy就需要建议新的区间关系。首先将fy指向fx,这代表fx是区间的左端点,计算sum【fy】= sum【x】- sum【y】+ s;这里同样用的是向量法。
这样建立联系与判断悖论都可以表达了,接下来就是一些细节了,比如在更新区间的时候要进行路径的压缩,压缩的过程中需要对权值进行更新,目的是使每个已知区间最大化。
#include<iostream>
using namespace std;
const int maxn=200005;
int sum[maxn],pre[maxn];
int n,m;
void init()
{
for(int i=0; i<=n; i++)
{
pre[i]=i;
sum[i]=0;
}
}
int find(int x)
{
if(x==pre[x])
return x;
else
{
int root=find(pre[x]);
sum[x]+=sum[pre[x]];
return pre[x]=root;
}
}
int main()
{
while(cin>>n>>m)
{
init();
int cnt=0;
for(int i=0; i<m; i++)
{
int p,q,s;
cin>>p>>q>>s;
p--;
int fp=find(p),fq=find(q);
if(fp!=fq)
{
pre[fp]=fq;
sum[fp]=sum[q]-sum[p]+s;
}
else if(sum[p]-sum[q]!=s) cnt++;
}
cout<<cnt<<endl;
}
return 0;
}