zoukankan      html  css  js  c++  java
  • hdu3038How Many Answers Are Wrong(带权并查集)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038

    题解转载自https://www.cnblogs.com/liyinggang/p/5327055.html

    题目大意:有n个数,你不知道具体是啥,只知道有n个,然后输入m组数据,每组包含三个整数,a,b,s,表示区间[a,b]的整数和为s,输出有错误的数据的组数。

    解题思路:是个典型的带权并查集,难点就在于更新相对信息值。在查找和合并也要对相对信息值进行更新。

    做法是用一个数组存储某个节点到其根节点的距离。把区间的总和看成是两个端点的相对距离。

    极力推荐这位大牛的博客:http://blog.csdn.net/niushuai666/article/details/6981689

    这题让我学到了很多,特别是关于向量偏移,可以直接找到根节点与子节点的关系

     

    这题我们利用一个sum[]数组保存从某点到其祖先节点距离。

    1.从上图我们可以看出,当roota!=rootb时 如果将roota并入rootb,那么是不是 roota->rootb = b->rootb - b->roota

    然后我们可以知道 b->roota = a->roota - a->b

    所以最后可以推出 roota ->rootb = b->rootb + a->b - a->roota

    而roota的根节点是rootb,所以 roota->rootb = sum[roota]

    然后依次推出得到 sum[roota] = -sum[a]+sum[b]+v (这里的a要说明一下由于是区间 [a,b] ,[a,b] = [root,b]-[root,a-1],所以a要减一)

    2.如果roota==rootb 是不是 a和b的根节点已经相同了?所以我们只要验证 a->b是否与题中的长度一致了。

    所以 a->b = a->root - b->root

    然后得到表达式 v = sum[a]-sum[b] (一定要记住这里的sum都是相对于根节点的,sum的更新在路径压缩的时候更新了)

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 using namespace std;
     5 const int maxn=200005;
     6 int par[maxn],rank[maxn],ans;
     7 
     8 int find(int x)
     9 {
    10     if(par[x]==x)
    11         return x;
    12     int temp=find(par[x]);
    13     rank[x]+=rank[par[x]];
    14     return par[x]=temp;
    15 }
    16 
    17 void unite(int x,int y,int s)
    18 {
    19     int rootx=find(x);
    20     int rooty=find(y);
    21     if(rootx!=rooty)
    22     {
    23         par[rooty]=rootx;
    24         rank[rooty]=rank[x]+s-rank[y];  //用向量的思维,合并后rooy到rootx的距离就等于x到根距离加上x和y的距离减去y到rooty的距离 
    25     }
    26     else
    27     {
    28         if(rank[x]+s!=rank[y])
    29             ans++;
    30     }
    31 }
    32 
    33 signed main()
    34 {
    35     int n,m;
    36     while(scanf("%d%d",&n,&m)!=EOF)
    37     {
    38         for(int i=1;i<=n;i++)
    39             par[i]=i,rank[i]=0;
    40         ans=0;
    41         while(m--)
    42         {
    43             int a,b,s;
    44             scanf("%d%d%d",&a,&b,&s);
    45             a--;
    46             unite(a,b,s);
    47         }
    48         printf("%d
    ",ans);
    49     }
    50     return 0;
    51 }
    52  
  • 相关阅读:
    52、saleforce 第一篇
    nodejs自定义模块
    NodeJS require路径
    Angularjs ngTable使用备忘
    HTML5拖拽功能中 dataTransfer对象详解
    Javascript闭包深入解析及实现方法
    Grunt实例
    Grunt插件uglify
    javascript 将字符串当函数执行
    多个springboot项目部署在同一tomcat上,出现jmx错误
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/9445382.html
Copyright © 2011-2022 走看看