一、题面

HDU3038

二、分析

用并查集可以方便的判断两个位置是否有关系,这种关系可以通过是否有公共父节点判断,如果有公共父节点则可以直接判断是否正确,如果没有公共父节点,就可以把这个条件与之前的联系起来。同时需要设定sum,表示当前点到父节点的权值,这个权值方便后面的判断,这里有几种情况。

假设输入为$(x,y,w)$,那么对应父节点$fx = find(x), fy = find(y)$:

1.如果$fx==fy$:那么可以直接判断$w == sum[x] - sum[y]$.

2.如果$ x < y < fx < fy$:这里需要更新并查集的信息,$par[fx] = fy, sum[fx] = sum[y] - (sum[x] - w)$.

3.如果$ x < fx < y < fy$:此时,$par[fx] = fy, sum[fx] = sum[y] + (w - sum[x])$.

4.如果$ x < y < fy < fx$:此时,$par[fy] = fx, sum[fy] = sum[x] - sum[y] - w$.

分析上面四种情况,可以得出2和3可以合并,对于4,仔细分析一下, 相当于就是3的情况,只是因为$par[fy] = fx$,只是这样可以保证$sum$的值为正。注意在路径压缩时,对$sum$进行更新就可以了。

细心的朋友可能发现了,还有$x = y$的情况呢。对于这种情况,我们可以直接对输入的左值整体再往左移一下,就是输入的$u$变成$u-1$,这个对结果是没有影响的。但是如果不减,我们就要考虑$x=y$的情况了,前面我们已经初始化了$sum$初值为0,并且$x=y$的左右两边的情况我们是不能保证完全清楚的。所以这样把$x=y$变成了$(x-1,y]$这个区间的形式,就让问题又归到了我们上面讨论的情况,更简单了。

三、AC代码

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <fstream>
  5. #include <map>
  6.  
  7. using namespace std;
  8.  
  9. const int MAXN = 2e5+;
  10. int par[MAXN];
  11. int sum[MAXN];
  12.  
  13. void Init()
  14. {
  15. for(int i = ; i < MAXN; i++)
  16. par[i] = i;
  17. memset(sum, , sizeof(sum));
  18. }
  19.  
  20. int Find(int x)
  21. {
  22. if(par[x] == x)
  23. return x;
  24. int fx = par[x];
  25. par[x] = Find(fx);
  26. sum[x] = sum[fx] + sum[x];
  27. return par[x];
  28. }
  29.  
  30. bool Union(int x, int y, int w)
  31. {
  32. int fx = Find(x);
  33. int fy = Find(y);
  34. // if(fx != fy)
  35. // {
  36. // par[fx] = fy;
  37. // sum[fx] = w + sum[y] - sum[x];
  38. // return true;
  39. // }
  40. // else
  41. // {
  42. // return w == sum[x] - sum[y];
  43. // }
  44. if(fx < fy)
  45. {
  46. par[fx] = fy;
  47. sum[fx] = w + sum[y] - sum[x];
  48. return true;
  49. }
  50. else if(fx > fy)
  51. {
  52. par[fy] = fx;
  53. sum[fy] = sum[x] - w - sum[y];
  54. return true;
  55. }
  56. else
  57. {
  58. return w == sum[x] - sum[y];
  59. }
  60.  
  61. }
  62.  
  63. int main()
  64. {
  65. // freopen("input.txt", "r", stdin);
  66. int N, M;
  67. while(scanf("%d %d", &N, &M)!=EOF)
  68. {
  69. Init();
  70. int a, b, w, ans = ;
  71. for(int i = ; i < M; i++)
  72. {
  73. scanf("%d %d %d", &a, &b, &w);
  74. if(!Union(a-, b, w))
  75. ans++;
  76. }
  77. printf("%d\n", ans);
  78. }
  79. return ;
  80. }

HDU_3038 How Many Answers Are Wrong 【带权并查集】的更多相关文章

  1. HDU3038 How Many Answers Are Wrong —— 带权并查集

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 How Many Answers Are Wrong Time Limit: 200 ...

  2. hdu3038How Many Answers Are Wrong(带权并查集)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038 题解转载自:https://www.cnblogs.com/liyinggang/p/53270 ...

  3. HDU3038 How Many Answers Are Wrong[带权并查集]

    How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  4. 【HDU3038】How Many Answers Are Wrong - 带权并查集

    描述 TT and FF are ... friends. Uh... very very good friends -________-b FF is a bad boy, he is always ...

  5. hdu 3038 How Many Answers Are Wrong ( 带 权 并 查 集 )

    How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  6. How Many Answers Are Wrong(带权并查集)

    How Many Answers Are Wrong http://acm.hdu.edu.cn/showproblem.php?pid=3038 Time Limit: 2000/1000 MS ( ...

  7. HDU3038:How Many Answers Are Wrong(带权并查集)

    How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  8. HDU 3038 How Many Answers Are Wrong(带权并查集)

    太坑人了啊,读入数据a,b,s的时候,我刚开始s用的%lld,给我WA. 实在找不到错误啊,后来不知怎么地突然有个想法,改成%I64d,竟然AC了 思路:我建立一个sum数组,设i的父亲为fa,sum ...

  9. HDU 3038 - How Many Answers Are Wrong - [经典带权并查集]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...

  10. 【带权并查集】【HDU3038】【How Many Answers Are Wrong】d s

    这个题看了2天!!!最后看到这篇题解才有所明悟 转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4298091.html   ---by 墨染之樱 ...

随机推荐

  1. Linux3一些文件操作命令more,less,pr,head,tail,wc

    查看文件内容命令: more和less 用cat命令可以查看文件.有时候文件太大,可以用管道符号|配合more或者less一同使用. cat  <文本文件名称>|more cat  < ...

  2. BOOL运算符号(从C#入门经典第五版中摘录)

    只总结自己觉得难的哈: (1) var1=!var2;    //(非) (2) var1=var2&var3;    //(与) (3)var1=var2|var3;    //(或) (4 ...

  3. Luogu 3723 [AH2017/HNOI2017]礼物

    BZOJ 4827 $$\sum_{i = 1}^{n}(x_i - y_i + c)^2 = \sum_{i = 1}^{n}(x_i^2 + y_i^2 + c^2 - 2 * x_iy_i + ...

  4. Shell内置命令

    主要Shell内置命令 Shell有很多内置在其源代码中的命令.这些命令是内置的,所以Shell不必到磁盘上搜索它们,执行速度因此加快.不同的Shell内置命令有所不同. A.2.1  bash内置命 ...

  5. 网页中的foot底部定位问题

    有时候,我们会碰到这样一个问题. 网页底部一般有个foot对吧,放置一些友情链接版权声明什么的,这个模块是如何定位的? 要是直接放内容区域的下面的话,假如是内容区域的高度不够的话,那么foot下面是会 ...

  6. 黑盒测试实践--Day5 11.29

    黑盒测试实践--Day5 11.29 今天完成任务情况: 分析系统需求,完成场景用例设计 小组负责测试的同学学习安装自动测试工具--QTP,并在线学习操作 小黄 今天的任务是完成场景测试用例的设计.在 ...

  7. (转)通过Javascript得到URL中的参数(query string)

    原文地址:http://www.cnblogs.com/season-huang/p/3322561.html 我们知道,"GET"请求中,通常把参数放在URL后面,比如这样htt ...

  8. 301 MovedPermanently 重定向

    页面永久性移走(301重定向)是一种非常重要的“自动转向”技术. 301重定向可促进搜索引擎优化效果 从搜索引擎优化角度出发,301重定向是网址重定向最为可行的一种办法.当网站的域名发生变更后,搜索引 ...

  9. C# worksheet设置Excel样式

    1.例子导出Excel的样式 样式代码 public void Exportdatagridviewtoexcel(string Textname) { SaveFileDialog savedial ...

  10. strcmp返回值布尔类型的判断

    strcmp: 用于比较两个字符串,原型如下: int strcmp ( char const *s1, char const *s2):如果s1小于s2,strcmp函数返回一个小于零的值.如果s1 ...