【BZOJ】1202: [HNOI2005]狡猾的商人

【题意】w组数据,给定n和m,给出m段区间[s,t](1<=s<=t<=n)的数字和,求是否矛盾。n<100,m<1000,w<100。

【算法】带权并查集

【题解】由于存在负数,唯一判断信息合法性的途径只有多个已知区间能组成一个已知大区间。

假设有n+1个点0~n表示sum[0]~sum[n],对这些点维护带权并查集,令d[x]表示sum[x]-sum[fa[x]]。

一个已知区间实际上是sum[t] - sum[s-1],如果s-1和t不属于同一个集合就并起来,并且更新d。(注意前缀和方向)

如果属于同一个集合就可以判断是否合法。

最后要注意find过程的执行顺序:int t=find(fa[x]); d[x]+=d[fa[x]]; fa[x]=t;

复杂度O(w*m)。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=110;
int fa[maxn],d[maxn];
int n,m,T;
int find(int x){
    if(fa[x]==x)return x;
    int t=find(fa[x]);
    d[x]+=d[fa[x]];
    fa[x]=t;
    return fa[x];
}
int main(){
    scanf("%d",&T);
    while(T--){
        memset(d,0,sizeof(d));
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++)fa[i]=i;
        bool flag=0;
        for(int i=1;i<=m;i++){
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            x--;
            int p=find(x),q=find(y);
            if(p!=q){
                fa[q]=p;
                d[q]=d[x]+w-d[y];
            }
            else if(d[y]-d[x]!=w){flag=1;break;}
        }
        if(flag)printf("false\n");else printf("true\n");
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/onioncyc/p/6234769.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值