这个题本质上和3635是一样的,到不如说比那个还简单的多:只要记录每个观众相对于自己所在集合的标记元素的偏移,在压缩路径时注意偏移的累加即可。如果新规则的两个观众已经在同一个集合内(在同一集合表示他们之间有严格的顺序关系),则判断新规则是否和原来的规则兼容((off[a]+x)%300 == off[b]),不兼容则累计错误。
同样这道题我也浪费了很长时间,其一是误以为合并到同一集合的观众一定要坐到同一行,其二是第21行我直接写成了off[rb]=x,root[rb]=ra,整整调试了一晚上= =|||
为什么这种错误会浪费一个晚上呢?因为各种细节错误,什么从0开始编号和从1开始编号啦、freopen语句没有注释啦(因为我这个版本的emacs里调用gdb时输入比较麻烦,而且eshll不支持输入重定向,只能用这个了)、数组开小啦等等。巨大的逻辑错误被掩藏在这些细微的错误里,真心蛋疼。
#include <cstdio>
#include <cstring>
int root[50005], off[50005];
int find(int u){
if (u == root[u]) return u;
int t = find(root[u]);
off[u]=(off[u]+off[root[u]])%300;
return root[u] = t;
}
int main(){
int n,m,a,b,x;
while (EOF != scanf("%d %d", &n, &m)){
int r = 0;
for (int i = 0; i < n; ++i)
root[i] = i, off[i] = 0;
for (int i = 0; i < m; ++i){
scanf("%d %d %d", &a, &b, &x);
int ra = find(--a), rb = find(--b);
if (ra == rb) r+=((off[a]+x)%300==off[b]?0:1);
else off[rb]=(off[a]-off[b]+x+600)%300,root[rb]=ra;
}
printf("%d\n", r);
}
return 0;
}