具體學習參考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;
}