分析:
因为要判断正误,最直接的为 a == a,b == b,c != c,可以判断语句错误,但大多数情况不能直接判断,就需要转换,例如:1-5=5,6-10=10,1-10=8,根据这三个语句就可以判断有一个错误。题目给出的是闭区间,可以转换为左开右闭区间,就可以运用(a,b]+(b,c]=(a,c],令par[x]为x到根的距离,当ab不同根时,以a的根作为b的根的根,par[r2]=par[a]+c-par[b].若ab同根,则par[b]-par[a]就为ab的距离。
int find(int x)
{
if (par[x] == x) return x;
int ret = find(par[x]);
val[x] += val[par[x]];
return par[x] = ret;
}
当时一直wa,后来发现是着出的问题。
wa代码:
/*
if (par[x] == x) return x;
val[x] += val[par[x]];
return par[x] = find(par[x]);
*/
后来仔细想了一下,递归find(par[x])的过程中,par[x]的根会更新,所以要先递归,记录下答案。
完整代码附上:
#include <iostream>
using namespace std;
const int maxn = 2e5 + 10;
int par[maxn];
int val[maxn];
void init(int n)
{
for (int i = 0; i <= n; i++) {
par[i] = i;
val[i] = 0;
}
return;
}
int find(int x)
{
if (par[x] == x) return x;
int ret = find(par[x]);
val[x] += val[par[x]];
return par[x] = ret;
/*if (par[x] == x) return x;
val[x] += val[par[x]];
return par[x] = find(par[x]);
*/
}
int main(void)
{
int n, m;
while (cin >> n >> m) {
int ans = 0;
init(n);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
a--;
int r1 = find(a);
int r2 = find(b);
if (r1 != r2) {
par[r2] = r1;
val[r2] = val[a] + c - val[b];
}
else {
if (val[b] - val[a] != c) {
ans++;
}
}
}
cout << ans << endl;
}
return 0;
}