带权并查集
题目链接:https://cn.vjudge.net/problem/HDU-3038
具体大意:给你多次询问,每一次输入三个值,前两个代表区间,最后一个代表这个区间的值。问你这多次询问中有几次时候矛盾的。
举个例题
1 2 3
1 2 4 ,这不就矛盾了,,,
具体思路:首先每一个点都是自己的区间,在每一次更新的过程中,这个点的父节点是当前点往前最多知道到哪个点的区间是清楚的。这样的话,每一次更新的时候,如果当前的区间已经知道了。比如说 3 4 5,那么就直接将1到4的距离减去1 2 的距离,得到的就是3 到5 的距离,然后再比较就可以了。
如果当前的区间不清楚,那么就需要更新,尽量往前更新。比如说 3 4 5,假设3的父亲节点1, 4的父亲节点是2
1 2 3 4
这样的话,就能够计算出1到2 的距离,也就是3的父亲节点和4的父亲节点的距离,然后再将4的父亲节点进行更新、
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 # define inf 0x3f3f3f3f 5 const int maxn =2e5+100; 6 int father[maxn]; 7 int sum[maxn]; 8 int Find(int t) 9 { 10 if(t==father[t]) 11 return t; 12 int tmp=father[t]; 13 father[t]=Find(father[t]); 14 sum[t]+=sum[tmp]; 15 return father[t]; 16 } 17 int main() 18 { 19 int n,m; 20 while(~scanf("%d %d",&n,&m)) 21 { 22 for(int i=0; i<=n; i++) 23 { 24 father[i]=i,sum[i]=0; 25 } 26 int ans=0; 27 int st,ed,val; 28 for(int i=1; i<=m; i++) 29 { 30 scanf("%d %d %d",&st,&ed,&val); 31 st--; 32 int t1=Find(st); 33 int t2=Find(ed); 34 if(t1==t2&&sum[ed]-sum[st]!=val) 35 ans++; 36 else if(t1>t2) 37 { 38 father[t1]=t2; 39 sum[t1]=sum[ed]-sum[st]-val; 40 } 41 else if(t1<t2) 42 { 43 father[t2]=t1; 44 sum[t2]=sum[st]+val-sum[ed]; 45 } 46 } 47 printf("%d\n",ans); 48 } 49 return 0; 50 }