题意:对于一个整数序列,每次指令为a b c,表示序列中从第a项加到第b项的和为c。若某条指令与前面指令所传达的信息矛盾,则视为该指令错误,否则视为该指令正确。给出一串指令,问错误指令的数量为多少。
解法:类似POJ 1182 食物链。用并查集做,每个节点有两个参数,比如对于节点x,一个是f,表示其根节点的编号;另一个是r,表示前x项之和减去前x.f项之和的差值。然后判定就好了。
tag:并查集
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-11-28 08:32 4 * File Name: DS-HDU-3038.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 9 using namespace std; 10 11 struct node{ 12 int f, r; 13 }; 14 15 int n, m, ans; 16 node a[200005]; 17 18 int find(int x) 19 { 20 if (x != a[x].f){ 21 int y = a[x].f; 22 a[x].f = find(a[x].f); 23 a[x].r = a[x].r + a[y].r; 24 } 25 return a[x].f; 26 } 27 28 void merge(int ta, int tb, int s, int fa, int fb) 29 { 30 a[fa].f = fb; 31 a[fa].r = a[tb].r - a[ta].r - s; 32 } 33 34 bool ok(int ta, int tb, int s, int fa, int fb) 35 { 36 return s == (a[tb].r - a[ta].r); 37 } 38 39 void init() 40 { 41 ans = 0; 42 for (int i = 0; i <= n; ++ i){ 43 a[i].f = i; 44 a[i].r = 0; 45 } 46 47 int ta, tb, s; 48 for (int i = 0; i < m; ++ i){ 49 scanf ("%d%d%d", &ta, &tb, &s); 50 -- ta; 51 52 int t1 = find(ta), t2 = find(tb); 53 if (t1 != t2) 54 merge(ta, tb, s, t1, t2); 55 else 56 if (!ok(ta, tb, s, t1, t2)) ++ ans; 57 } 58 } 59 60 int main() 61 { 62 while (scanf ("%d%d", &n, &m) != EOF){ 63 init(); 64 printf ("%d ", ans); 65 } 66 return 0; 67 }