注意这种合并区间的问题往往需要把所有左端点-1,使得[1,5] [6,10]可以合并
题意:
有M个数,不知道它们具体的值,但是知道某两个数之间(包括这两个数)的所有数之和,现在给出N个这样的区间和信息,需要判断有多少个这样的区间和与前边已知的区间和存在矛盾。例如给出区间和[1,4]为20,[3,4]为15,再给出[1,2]为30,显然这个[1,2]的值就有问题,它应该为20-15=5。
思路:
// Decline is inevitable, romance will last forever.
//HDU3038 How Many Answers Are Wrong
//#include <bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string>
#include <cstdio>
using namespace std;
#define mst(a, x) memset(a, x, sizeof(a))
#define INF 0x3f3f3f3f
#define P 998244353
//#define int long long
const int maxn = 2e5 + 10;
const int maxm = 3e5*4 + 10;
int n, m;
int fa[maxn];
int sum[maxn]; //表示某节点到其根之间的和
int find(int x) {
if(x == fa[x]) return x;
int root = find(fa[x]); //找到根节点
sum[x] += sum[fa[x]]; //权值合并 更新
return fa[x] = root; //压缩路径
}
int s, ans = 0;
void merge(int x, int y) {
int fx = find(x);
int fy = find(y);
if(fx != fy) {
fa[fy] = fx;
sum[fy] = sum[x] - sum[y] + s;
}
else if(sum[y] - sum[x] != s) ans++;
}
void init() {
for(int i = 0; i <= n; i++)
{
fa[i] = i;
sum[i] = 0;
}
}
void solve() {
while(cin >> n >> m) {
init();
ans = 0;
while(m--) {
int x, y;
scanf("%d%d%d", &x, &y,&s);
x--; //可以让类似【1,5】【6,10】这样的区间可以合并
merge(x, y);
}
printf("%d\n", ans);
}
}
signed main() {
// ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
// int T; scanf("%d", &T); while(T--)
// int T; cin >> T; while(T--)
solve();
return 0;
}