一、题面

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代码

 #include <cstdio>
#include <iostream>
#include <cstring>
#include <fstream>
#include <map> using namespace std; const int MAXN = 2e5+;
int par[MAXN];
int sum[MAXN]; void Init()
{
for(int i = ; i < MAXN; i++)
par[i] = i;
memset(sum, , sizeof(sum));
} int Find(int x)
{
if(par[x] == x)
return x;
int fx = par[x];
par[x] = Find(fx);
sum[x] = sum[fx] + sum[x];
return par[x];
} bool Union(int x, int y, int w)
{
int fx = Find(x);
int fy = Find(y);
// if(fx != fy)
// {
// par[fx] = fy;
// sum[fx] = w + sum[y] - sum[x];
// return true;
// }
// else
// {
// return w == sum[x] - sum[y];
// }
if(fx < fy)
{
par[fx] = fy;
sum[fx] = w + sum[y] - sum[x];
return true;
}
else if(fx > fy)
{
par[fy] = fx;
sum[fy] = sum[x] - w - sum[y];
return true;
}
else
{
return w == sum[x] - sum[y];
} } int main()
{
// freopen("input.txt", "r", stdin);
int N, M;
while(scanf("%d %d", &N, &M)!=EOF)
{
Init();
int a, b, w, ans = ;
for(int i = ; i < M; i++)
{
scanf("%d %d %d", &a, &b, &w);
if(!Union(a-, b, w))
ans++;
}
printf("%d\n", ans);
}
return ;
}

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. - description 方法作用

    自定义一个Person类 @interface Person : NSObject { int _age; double _height; double _weight; NSString *_nam ...

  2. Docker学习笔记_安装ActiveMQ

    一.实验环境 1.宿主机OS:Win10 64位 2.虚拟机OS:Ubuntu18.04,虚拟机名称:Ubuntu18VM1,虚拟机IP:192.168.8.25 3.操作账号 :Docker 4.在 ...

  3. Django--static静态文件引用

    需求 引用静态文件的目录不写死 "django.core.context_processors.static", html引用 1 <script src="{{ ...

  4. Java学习——JSTL标签与EL表达式之间的微妙关系

    原文总结的太好了,忍不住记录.转发. 原文地址:http://blog.csdn.net/u010168160/article/details/49182867 目录(?)[-] 一EL表达式 EL相 ...

  5. 列表推导式对比For循环执行效率

    我们在前面的学习中都知道,如果把1-10以内的元素追加到一个新的列表表中,如果使用for循环我们可以这么做: a = [] for i in range(1,11): a.append(i) prin ...

  6. javascript总结5:js常见的数据类型

    1 Number 数字类型 :包含正数,负数,小数 十进制表示: var n1 =23; 十六进制表示法:从0-9,a(A)-f(F)表示数字.以0x开头. var n2 = 0x42 2 字符串数据 ...

  7. Ubuntu安装开发版pidgin支持lwqq插件

    sudo add-apt-repository ppa:lainme/pidgin-lwqq  """添加pidgin-lwqq源""" s ...

  8. (转)Linux环境进程间通信系列(五):共享内存

    原文地址:http://www.cppblog.com/mydriverc/articles/29741.html 共享内存可以说是最有用的进程间通信方式,也是最快的 IPC 形式.两个不同进程 A ...

  9. POJ3041 Asteroids(二分图最小点覆盖)

    Description Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape o ...

  10. delphi 指针 认识

    delphi 指针分为类型指针和无类型指针: 类型指针分为PChar.PInteger.PString等. 无类型指针Pointer. PPChar/PP...为指针的指针 @和Addr一样,为获取变 ...