bzoj1202--带权并查集+前缀和

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\n");else printf("true\n");
    }
    return 0;
}
时间: 2024-10-11 12:00:44

bzoj1202--带权并查集+前缀和的相关文章

【bzoj 1202】[HNOI2005] 狡猾的商人(图论--带权并查集+前缀和)

题意:一个账本记录了N个月以来的收入情况,现在有一个侦探员不同时间偷看到M段时间内的总收入,问这个账本是否为假账. 解法:带权并查集+前缀和.   判断账本真假是通过之前可算到的答案与当前读入的值是否相同来完成.那么就是只有知道新读入的区间2端的(在相同区域内的!!)前缀和才可以判断,也就是这2个端点之前被纳入了相同的区域内才可以判断.于是,我们就可以想到并查集了.(( ′? ??`) 真的么......)   假设已知x~y月的总收入为d,那么s[y]-s[x-1]=d.一般前缀和是算上自己的

【带权并查集】【离散化】vijos P1112 小胖的奇偶

每个区间拆成r和l-1两个端点,若之内有偶数个1,则这两个端点对应的前缀的奇偶性必须相同,否则必须相反. 于是可以用带权并查集维护,每个结点储存其与其父节点的奇偶性是否相同,并且在路径压缩以及Union时进行分类讨论即可. 由于n太大,要对两个端点进行离散化. #include<cstdio> #include<algorithm> using namespace std; int fa[10010]; bool rel[10010]; int findroot(int x){ i

「带权并查集」奇偶游戏

奇偶游戏 原题链接:奇偶游戏 题目大意 给你N个区间,每个区间给你它含1的奇偶性,问你哪些询问逻辑上冲突 题目题解 一道带权并查集的题,让我对带权并查集有了更深入的理解,带权并查集可以分为两种(在这道题中) "边带权"并查集 "扩展域"并查集 两种方法都是思维上的不同所造成的,其中第一种解法是最常见的,第二种解法在代码实现上是最简单的,我们先来对第一种进行探究 边带权,很明显,我们要在并查集的边上进行一个储存边权的操作,我们这里用d来表示当前节点到根节点的Xor值,

hdu3038(带权并查集)

题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 题意: n表示有一个长度为n的数组, 接下来有m行形如x, y, d的输入, 表示从第x,个元素到第y个元素的和为d(包括x, 和y), 问m行输入里面有几个是错误的(第一个输入是正确的); 思路: 很显然带权并查集咯,我们可以用距离的概念代替和的概念比较好理解一点,d表示x到y的和即x到y的距离; 可以用rank[x]表示x到其父亲节点的距离,  将正确的距离关系合并到并查集中

【POJ1182】 食物链 (带权并查集)

Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之

【poj 1988】Cube Stacking(图论--带权并查集 模版题)

题意:有N个方块,M个操作{“C x”:查询方块x上的方块数:“M x y”:移动方块x所在的整个方块堆到方块y所在的整个方块堆之上}.输出相应的答案. 解法:带权并查集.每堆方块作为一个集合,维护3个数组:fa[x]表示x方块所在堆的最顶部的方块:d[x]表示x方块所在堆的最底部的方块:f[x]表示x方块方块x上的方块数. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<

并查集练习2(带权并查集)

明天旅游去爬山逛庙玩,今天练一天然后早早睡觉啦~ poj1703 Find them, Catch them (带权并查集) 1 #include<cstdio> 2 const int N=1e5+1; 3 int f[N]; 4 int r[N];//表示与父节点的关系,0同类,1不同类 5 int n; 6 void init(){ 7 for(int i=1;i<=n;++i){ 8 f[i]=i; r[i]=0; 9 } 10 } 11 int fin(int x){ 12 i

Lightoj1009 Back to Underworld(带权并查集)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Back to Underworld Time Limit:4000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Description The Vampires and Lykans are fighting each other to death. The war has become so fierc

[NOIP摸你赛]Hzwer的陨石(带权并查集)

题目描述: 经过不懈的努力,Hzwer召唤了很多陨石.已知Hzwer的地图上共有n个区域,且一开始的时候第i个陨石掉在了第i个区域.有电力喷射背包的ndsf很自豪,他认为搬陨石很容易,所以他将一些区域的陨石全搬到了另外一些区域. 在ndsf愉快的搬运过程中,Hzwer想知道一些陨石的信息.对于Hzwer询问的每个陨石i,你必须告诉他,在当前这个时候,i号陨石在所在区域x.x区域共有的陨石数y.以及i号陨石被搬运的次数z. 输入描述: 输入的第一行是一个正整数T.表示有多少组输入数据. 接下来共有

hdu 1558 Segment set【基础带权并查集+计算几何】

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3599    Accepted Submission(s): 1346 Problem Description A segment and all segments which are connected with it compose a segment set