BZOJ1202: [HNOI2005]狡猾的商人

Posted ONION_CYC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1202: [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

 

以上是关于BZOJ1202: [HNOI2005]狡猾的商人的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1202: [HNOI2005]狡猾的商人 并查集好题

BZOJ 1202 [HNOI2005]狡猾的商人

bzoj1202 HNOI2005—狡猾的商人

bzoj1202 [HNOI2005]狡猾的商人

bzoj1202: [HNOI2005]狡猾的商人(差分约束)

BZOJ 1202 [HNOI2005]狡猾的商人