HDU 3038 How many answer are wrong (并查集)

题目意思大概是这样的  给你一个n和m分别代表在1-n这些区间内给你m组数字  每组有三个值  分表代表从 L 到 R 的和为value  问你互相矛盾的组合有多少个、


并查集经典问题  刚开始不理解这道题的解法是什么意思   怎么都看不懂  就背下来了 过了好久才看懂是什么意思 

思路是这样的  我们维护两个数组  一个是并查集的fa数组不用多说  另一个是sum数组 这歌数组sum[i]    是用来记录 I 到根节点的距离  我们在发现两个点的根节点不同并合并 这时候sum数组中的值并未更新   而是下一次用到他们的find函数的时候才更新了他们的值


 

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 200005;
int fa[maxn];
int sum[maxn];
int find(int x)
{
	if(x == fa[x])return fa[x];
	int temp = find(fa[x]);
	sum[x] += sum[fa[x]];
	return fa[x] = temp;
} 
int main()
{
		int n, m;
		while (cin >> n >> m) {
			int ans = 0;
			for (int i = 0; i <= n; i ++) 
				fa[i] = i;
			memset(sum , 0, sizeof(sum));
			int a, b, value;
			for (int i = 0; i < m; i ++) {
				cin >> a >> b >> value;
				a--;
				int xx = find(a);
				int yy = find(b);
				if(xx != yy) {
					fa[yy] = xx;//把yy的父亲变成xx
					sum[yy] = sum[a] - sum[b] + value;//sum[yy]代表yy到xx的距离  这句话可能需要好好理解下
				}
				else {                                                                                          
					if(sum[b] - sum[a] != value)ans ++;
				}
			}
			cout << ans << endl;
		}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值