有的时候在这些边中添加一些额外的信息可以更好的处理需要解决的问题.
在每条边中记录额外的信息的并查集就是带权并查集.
查找:
int get(int x)
{
if(x!=f[x])
{
int tmp=f[x];
f[x]=get(f[x]);
val[x]+=val[tmp];//连接,并修改权值
}
return f[x];
}
合并:
void unite(int a,int b,int v)
{
int x=get(a);
int y=get(b);
if(x==y)
{
if(val[a]-val[b]!=v)//判断是否与已经计算出来的相同
ans++;
}
else{
f[x]=y;
val[x]=-val[a]+val[b]+v;//修改权值
}
}
hdu 3038:https://vjudge.net/problem/HDU-3038
题意:n表示有一个长度为n的数组, 接下来有m行形如x, y, d的输入, 表示从第x,个元素到第y个元素的和为d(包括x, 和y), 问m行输入里面有几个是错误的(第一个输入是正确的);
解析:
首先题目是闭区间,转化为开区间好计算判断(l-1,r)或者(l,k+1)
带权并查集模板题,判断合法
首先如果get(a)==get(b),表示可以通过前面的计算出后面的,呢就判断是否合法(与计算出的比较是否相等)
如果!=,呢就计算出新的结点的情况
#include
#define MAXN 1000005
using namespace std;
int f[MAXN];
int val[MAXN];
int ans=0;
void init()
{
for(int i=0;i
https://vjudge.net/problem/POJ-1182
动物王国中有三类动物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句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
1) 当前的话与前面的某些真的话冲突,就是假话;
2) 当前的话中X或Y比N大,就是假话;
3) 当前的话表示X吃X,就是假话。
你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数
解析:
1.如果x==y&v==2,或者x>n||y>n直接假话
2. 2 x y =>x y的关系1,y x的关系是 (-1+3)%3==2,判断他是否等于v-1,但是v不能为3
ac:
#include
#include
#include
#include
#define MAXN 1000005
using namespace std;
int f[MAXN];
int val[MAXN];
int ans=0;
void init()
{
for(int i=0;in||y>n)
ans++;
else unite(x,y,w);
}
printf("%d\n",ans);
return 0;
}
/*
10 3
2 1 3
2 3 1
3 3 1
*/