狡猾的商人 [bzoj1202,HNOI2005]

33 篇文章 0 订阅
20 篇文章 0 订阅

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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值