zoukankan      html  css  js  c++  java
  • hdu3038加权(扩展)并查集

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/3038/

    参考博客:

    https://blog.csdn.net/weixin_44580710/article/details/86668200?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

    这是一道带权并查集的题目,设置了根节点到子节点之间的距离,可以利用向量性质更新每段上的值,假定结点编号为a的结点的值S[a]在结点之后的连线上,所以查询[l,r]的时候实际上是看[l,r+1]段,如果定义结点之前的连线上是该结点的值,则查询的区间实际上是[l-1,r]。利用向量性质实际上更新fx->fy=fx->x + x->y - fy->y ,对于一个节点i,S[i]就表示根节点到这个点的区间和。

    代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef unsigned int ui;
     4 typedef long long ll;
     5 typedef unsigned long long ull;
     6 #define pf printf
     7 #define mem(a,b) memset(a,b,sizeof(a))
     8 #define prime1 1e9+7
     9 #define prime2 1e9+9
    10 #define pi 3.14159265
    11 #define lson l,mid,rt<<1
    12 #define rson mid+1,r,rt<<1|1
    13 #define scand(x) scanf("%llf",&x) 
    14 #define f(i,a,b) for(int i=a;i<=b;i++)
    15 #define scan(a) scanf("%d",&a)
    16 #define mp(a,b) make_pair((a),(b))
    17 #define P pair<int,int>
    18 #define dbg(args) cout<<#args<<":"<<args<<endl;
    19 #define inf 0x3f3f3f3f
    20 const int maxn=1e6+10;
    21 int n,m,t;
    22 inline int read(){
    23     int ans=0,w=1;
    24     char ch=getchar();
    25     while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    26     while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
    27     return ans*w;
    28 }
    29 int ans;
    30 int f[maxn],s[maxn];
    31 void init()
    32 {
    33     f(i,1,n)
    34     {
    35         f[i]=i;
    36         s[i]=0;
    37     }
    38     ans=0;
    39 }
    40 int find(int x)
    41 {
    42     if(x==f[x])return x;//到达根结点的时候不需要有任何操作,只需要返回根就行
    43     int tmp=f[x];//暂存f当前的根,因为在路径压缩之后当前的根节点会发生变化 
    44     f[x]=find(f[x]); 
    45     s[x]+=s[tmp];//将根节点的值加到当前结点上,相当于前缀和
    46     return f[x]; 
    47 }
    48 void Union(int x,int y,int num)
    49 {
    50     int fx=find(x);
    51     int fy=find(y);
    52     if(fx==fy)
    53     {
    54         if(s[y]-s[x]!=num)ans++;//x->y=rooty->y - rootx->x
    55     }
    56     else 
    57     {
    58         f[fy]=fx;//保持根节点的值比较小 
    59         //fx根节点指向了新的结点,所以他的值需要改变,而原来以fx为根的结点的f值还未变化,所以s值不变 
    60         s[fy]=s[x]+num-s[y];//s[t]代表的是root->t的和 
    61         //故有rootx->rooty=rootx->x+x->y-rooty->y=s[x]+num-s[y] 
    62     }
    63 }
    64 int main()
    65 {
    66     //freopen("input.txt","r",stdin);
    67     //freopen("output.txt","w",stdout);
    68     std::ios::sync_with_stdio(false);
    69     while(scanf("%d%d",&n,&m)!=EOF)
    70     {
    71         init();
    72         int u,v,w;
    73         f(i,1,m)
    74         {
    75             u=read(),v=read(),w=read();
    76             Union(u-1,v,w);//如果f是从0开始的话Union(u,v+1,w)也可用 
    77         }
    78     //    f(i,1,n)cout<<i<<":"<<f[i]<<":"<<s[i]<<endl;
    79         pf("%d
    ",ans);
    80     }
    81  } 
  • 相关阅读:
    洛谷P3275 [SCOI2011]糖果
    2018年12月30&31日
    洛谷P4114 Qtree1
    洛谷P4116 Qtree3
    洛谷P4315 月下“毛景树”
    洛谷P1505 [国家集训队]旅游
    洛谷P2253 好一个一中腰鼓!
    CF616D Longest k-Good Segment
    洛谷P3979 遥远的国度
    洛谷P2486 [SDOI2011]染色
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12563189.html
Copyright © 2011-2022 走看看