zoukankan      html  css  js  c++  java
  • bzoj1202 [ HNOI2005 ] --带权并查集+前缀和

    http://www.lydsy.com/JudgeOnline/problem.php?id=1202

          记s[i]=a[1]+a[2]+...+a[i],即s[i]为前缀和。再令v[i]=s[f[i]]-s[i],其中f[i]为i的父亲。对于每个读入的x,y,k,将x,y视为结点,如果x与y的根结点相同,因为v[y]-v[x]=s[f[y]]-s[y]-s[f[x]]-s[x]且f[y]=f[x],所以v[y]-v[x]就是区间[x,y]的和,所以只需要判断v[y]-v[x]是否等于k就可以了。如果x与y的根结点不相同,合并两个节点并更新信息。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,i,j,m,f[101],w,x,y,k,v[101];
    bool flag;
    int find(int x){
        if(x==f[x])return x;
        int tmp=f[x];                     //记录原来的父亲
        f[x]=find(f[x]);
        v[x]+=v[tmp];                     //更新结点信息
        return f[x];
    }
    bool union1(int x,int y,int k){
        int fx=find(x),fy=find(y);
        if(fx==fy){
            if(v[y]-v[x]!=k)return 0;
        }else{
            f[fy]=fx;
            v[fy]=k-v[y]+v[x];             //更新结点信息
        }
        return 1;
    }
    int main()
    {
        scanf("%d",&w);
        while(w--){
            memset(v,0,sizeof(v));
            flag=0;
            scanf("%d%d",&n,&m);
            for(i=0;i<=n;i++)f[i]=i;
            for(i=1;i<=m;i++){
                scanf("%d%d%d",&x,&y,&k);
                if(!flag&&!union1(x-1,y,k))flag=1;
            }
            if(flag)printf("false
    ");else printf("true
    ");
        }
        return 0;
    }
  • 相关阅读:
    原型模式
    Object.defineProperties()和Object.defineProperty()方法
    访问器属性:setter()函数和getter()函数
    2019.7.11刷题统计
    2019.7.10刷题统计
    2019.7.9刷题统计
    2019.7.8刷题统计
    2019.7.7刷题统计
    2019.7.6刷题统计
    2019.7.5刷题统计
  • 原文地址:https://www.cnblogs.com/gjghfd/p/5680075.html
Copyright © 2011-2022 走看看