AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1202
[分析]
因为每月的总收入可以为正,也可以为负,所以要比较两个区间是否相符,当且仅当它们边界都相同时才能比较。我们设w[i]表示第1~i个月的总收入与第1~(fa[i]-1)个月的总收入之差,及第fa[i]~i个月的总收入。
如图。
若i-1,j在同一个集合中,则第i~j个月的总收入为w[j]-w[i-1];
当输入s,t,w时,若s-1,t在同一个集合中,则判断w是否等于(w[t]-w[s-1]),若不相等,则直接输出false。
如图。
当输入s,t,w时,若s-1,t不再同一个集合中,则合并两个集合,fa[find(s-1)]=find(t),然后更新旧的find(s-1)到新的find(s-1)的w[find(s-1)]。
如图,w[find(s-1)]=AB=AD-(BC+CD)=w[t]-w[s-1]-w (w[s-1]为未更新前的值)
最后,在路径压缩的时候,要记得w[x]+=w[fa[x]]。
#include <iostream>
#include <cstdio>
using namespace std;
int t,n,m;
int fa[20000],w[20000];
int find(int x){
if(fa[x]==x)return x;
int tmp=find(fa[x]);
w[x]+=w[fa[x]];
fa[x]=tmp;
return tmp;
}
int main(){
scanf("%d",&t);
for(int i=1;i<=t;i++){
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)fa[i]=i,w[i]=0;
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
int fx=find(x-1),fy=find(y);
if(fx==fy){
if(w[y]-w[x-1]!=z){
printf("false\n");
goto nxt;
}
}
else{
fa[fx]=fy;
w[fx]=w[y]-w[x-1]-z;
}
}
printf("true\n");
nxt:;
}
return 0;
}