思路:
由题意给定几组判断,如果与前面的相悖则为错误ans++,如果与前面不相悖则加入维护,
用带权的并查集维护给出的条件,l~r和为s,可以看成d[r]-d[l-1]==s和前缀和类似。
代码:
#include <bits/stdc++.h>
#define fastio ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
#define debug(a) cout << "debug : " << (#a) << " = " << a << endl
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const int mod = 998244353;
int n, m;
int ans;
int f[N], d[N];
int find(int x)
{
if (x != f[x])
{
int u = find(f[x]); //递归找x的根节点
//回溯更新
d[x] += d[f[x]]; //将x到新根节点的距离更新为原来:原来根据点到新根节点 + x到原来根节点
f[x] = u; //更新x根节点
}
return f[x];
}
//x所在的树根节点加入到y所在的树下方
void join(int x, int y, int w)
{
int f1 = find(x), f2 = find(y);
f[f1] = f2; //x的父节点成为y父节点的子节点
d[f1] = d[y] + w - d[x]; //将f1节点加到以f2为根据点的树下
}
int main()
{
fastio;
while (cin >> n >> m)
{
ans = 0;
for (int i = 0; i <= n; i++)
f[i] = i, d[i] = 0;
while (m--)
{
int l, r, w;
cin >> l >> r >> w;
l--;
if (find(l) == find(r))
{
if (d[l] - d[r] != w) //因为合并都是将l所在的树加入到r所在的树,所以d[l] - d[r]为正数
ans++;
}
else
join(l, r, w);
}
cout << ans << endl;
}
return 0;
}