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  } 
  • 相关阅读:
    IntelliJ IDEA 14.03 java 中文文本处理中的编码格式设置
    应聘感悟
    STL string分析
    CUDA SDK VolumeRender 分析 (1)
    BSP
    CUDA SDK VolumeRender 分析 (3)
    CUDA SDK VolumeRender 分析 (2)
    Windows软件发布时遇到的一些问题
    Ten Commandments of Egoless Programming (转载)
    复习下光照知识
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12563189.html
Copyright © 2011-2022 走看看