带权并查集

题目链接: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 }

 

posted @ 2018-09-24 11:42  Let_Life_Stop  阅读(117)  评论(0编辑  收藏  举报