题目思路
看完题基本上能够知道是个带权并查集 判断冲突次数
但是有一个很妙的细节就是读入点之间的关系的时候
要对左边点的减1
至于为什么 我们来讨论一组数据
10 5
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
这个数据最后应该得到的结果是0
但如果不处理第一个输入值的话最后结果会是5
这个时候1到5每个点都处于一个单独的集合
我们没有把他们合并起来 使得他们在读入的时候被看作冲突的值
所以我们需要先对第一个输入的值做一个减1的处理
以上思路来源:
https://blog.csdn.net/mengxiang000000/article/details/50580864
附上一个带权并查集的模板和一个讲带权并查集讲的挺好的博客
压缩路径+权值更新
int find(int x)
{
if (x != parent[x])
{
int t = parent[x];
parent[x] = find(parent[x]);
value[x] += value[t];
}
return parent[x];
}
合并
int px = find(x);
int py = find(y);
if (px != py)
{
parent[px] = py;
value[px] = -value[x] + value[y] + s;
}
https://blog.csdn.net/yjr3426619/article/details/82315133
ac代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 2e5+5;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1000000007;
//998244353
int f[maxn],sum[maxn],up[maxn],cot;
int findx(int x)
{
if(f[x]!=x)
{
int t=f[x];
f[x]=findx(f[x]);
sum[x]+=sum[t];
}
return f[x];
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
int ans=0;
for(int i=1;i<=n;i++)f[i]=i,sum[i]=0;
for(int i=1;i<=m;i++)
{
int a,b,v;
scanf("%d%d%d",&a,&b,&v);
a--;
int r1=findx(a);
int r2=findx(b);
if(r1!=r2)
{
f[r2]=r1;
sum[r2]=-sum[b]+sum[a]+v;
}else
{
if(sum[b]-sum[a]!=v)
{
ans++;
}
}
}
printf("%d\n",ans);
}
}