【模板】帶權並查集 HDU 3038
阿新 • • 發佈:2018-12-11
具體學習參考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; }