zoukankan      html  css  js  c++  java
  • 【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
    ");else printf("true
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    C# String.Compare 方法测试
    C#checked 与 unchecked
    C#枚举类型
    C#结构体
    C越界和溢出的区别
    python/matlab : 将txt文件中的数据读为numpy数组
    matlab程序里调用python文件
    Python
    Pycharm调试及快捷键技巧
    Pycharm远程连接服务器debug时报错
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6234769.html
Copyright © 2011-2022 走看看