一、题面

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. linux下方便的录屏命令

    linux下方便的录屏命令   ffmpeg -f x11grab -s 1024*768 -r 20 -i :0.0 -sameq ~/recode.mpg -r后是刷新屏率,   推出直接Ctrl ...

  2. Android NDK打印log到logcat的方法

    头文件 : <android/log.h> 函数: __android_log_print(ANDROID_LOG_XXX,LOG_TAG,content) 第一个参数是Log级别,比如: ...

  3. Apache ab命令

    一.简介 ab是apache自带的压力测试工具.ab非常实用,它不仅可以对apache服务器进行网站访问压力测试,也可以对或其它类型的服务器进行压力测试.比如nginx.tomcat.IIS等. 二. ...

  4. 41、Aspera下载安装运用

    参考:http://www.so.com/linkm=aLVHG%2FgJT4HyuVeK4%2BxX2LMFvF6oTiTCaruHE20pwjRia7DmVI2hIVfmw%2BFNPczCtvX ...

  5. LightOJ 1282 Leading and Trailing (数学)

    题意:求 n^k 的前三位和后三位. 析:后三位,很简单就是快速幂,然后取模1000,注意要补0不全的话,对于前三位,先取10的对数,然后整数部分就是10000....,不用要,只要小数部分就好,然后 ...

  6. datagrid 自定义 pager

    $(document).ready(function(){ var p = $('.easyui-datagrid').datagrid('getPager'); $(p).pagination({ ...

  7. Java之集合框架vector类设计原理

  8. Java Thread.join()详解--父线程等待子线程结束后再结束

    目录(?)[+] 阅读目录 一.使用方式. 二.为什么要用join()方法 三.join方法的作用 join 四.用实例来理解 打印结果: 打印结果: 五.从源码看join()方法   join是Th ...

  9. LibreOJ 6001 太空飞行计划(最大流)

    题解:首先源点向每个实验建边,流量为经费的值,实验向器材建边,值为无限大,器材向终点建边,值为价值 然后跑一遍最大流就能跑出所谓的最大闭合图的点值之和. 代码如下: #include<queue ...

  10. android Base64字符串与Bitmap相互转换

    /** * 将bitmap转换成base64字符串 * * @param bitmap * @return base64 字符串 */ public String bitmaptoString(Bit ...