HDU_3038 How Many Answers Are Wrong 【带权并查集】
一、题面
二、分析
用并查集可以方便的判断两个位置是否有关系,这种关系可以通过是否有公共父节点判断,如果有公共父节点则可以直接判断是否正确,如果没有公共父节点,就可以把这个条件与之前的联系起来。同时需要设定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 【带权并查集】的更多相关文章
- HDU3038 How Many Answers Are Wrong —— 带权并查集
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 How Many Answers Are Wrong Time Limit: 200 ...
- hdu3038How Many Answers Are Wrong(带权并查集)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038 题解转载自:https://www.cnblogs.com/liyinggang/p/53270 ...
- HDU3038 How Many Answers Are Wrong[带权并查集]
How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- 【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 ...
- 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 ...
- How Many Answers Are Wrong(带权并查集)
How Many Answers Are Wrong http://acm.hdu.edu.cn/showproblem.php?pid=3038 Time Limit: 2000/1000 MS ( ...
- HDU3038:How Many Answers Are Wrong(带权并查集)
How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- HDU 3038 How Many Answers Are Wrong(带权并查集)
太坑人了啊,读入数据a,b,s的时候,我刚开始s用的%lld,给我WA. 实在找不到错误啊,后来不知怎么地突然有个想法,改成%I64d,竟然AC了 思路:我建立一个sum数组,设i的父亲为fa,sum ...
- 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 ...
- 【带权并查集】【HDU3038】【How Many Answers Are Wrong】d s
这个题看了2天!!!最后看到这篇题解才有所明悟 转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4298091.html ---by 墨染之樱 ...
随机推荐
- C/C++代码覆盖率工具gcov、lcov
gcov是一个可用于C/C++的代码覆盖工具,是gcc的内建工具.下面介绍一下如何利用gcov来收集代码覆盖信息. 想要用gcov收集代码覆盖信息,需要在gcc编译代码的时候加上这2个选项 “-fpr ...
- pandas map, apply, applymap区别
map只对一个序列而言的. apply只是整个dataframe上任意一列或多列,或者一行或多行, 即可在任意轴操作. 在一列使用apply时,跟map效果一样. 多列时只能用apply. apply ...
- Django框架 之 跨域请求伪造
Django框架 之 跨域请求伪造 浏览目录 同源策略与Jsonp 同源策略 Jsonp jQuery对JSONP的实现 CORS 简介 两种请求 同源策略与Jsonp 同源策略 同源策略(Same ...
- linux下mariadb的下载与卸载
Linux下mariadb的安装 使用阿里云的mariadb yum install mariadb-server mariadb -y 启动mariadb数据库 systemctl start/st ...
- javascript总结16:数组array12
1 Array 对象 作用:Array 对象用于在变量中存储多个值. 1.1 数组定义 var ary = new Array();//通过创建对象的方式创建数组 var ary1 = [];// 直 ...
- gettimeofday()函数的使用方法
1.简介: 在C语言中可以使用函数gettimeofday()函数来得到精确时间.它的精度可以达到微妙,是C标准库的函数. 2.函数原型: #include<sys/time.h> int ...
- vba实现excel多表合并
Excel多表合并之vba实现 需求 保留列名,复制每一个excel里的数据,合并到一个excel 操作步骤 将要合并的文件放在同一文件夹下,复制过来就好(ps:最好不要直接操作原数据文件,避免操作失 ...
- C#多线程编程实战1.4终止线程
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- IEnumerable与IQueryable区别
最近在使用MongoDB的时候,发现查询很慢,一个根据Id查询的语句竟然用了50秒,debug了一下,没发现什么大问题,但是另一个查询的语句只用了2秒,对比了一下,发现50s的那个语句使用的IEnum ...
- .net core 图片合并,图片水印,等比例缩小,SixLabors.ImageSharp
需要引用 SixLabors.ImageSharp 和SixLabors.ImageSharp.Drawing 引用方法 NuGet包管理 添加程序包来源 https://www.myget.org/ ...