[HNOI2005]狡猾的商人 带权并查集
给定m个区间和,问是否有矛盾
复习一下,带权并查集保存着这个元素与祖先的关系
在合并的过程中就像向量合并一样,可以画出x->fa[x],y->fa[y],x->y这样的图方便理解
这篇文章解释得很清楚NOIAu
//#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
#include<stack>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mem(a) memset(a,0,sizeof a)
#define FOR(a) for(int i=1;i<=a;i++)
const int maxn=1e2+7;
int fa[maxn],v[maxn],flag,t;
int find(int x){
if(fa[x]==x)return x;
t=find(fa[x]);
v[x]+=v[fa[x]];
fa[x]=t;
return fa[x];
}
void work(int x,int y,int w){
int p=find(x),q=find(y);
if(p!=q){
fa[p]=q;
v[p]=v[y]-v[x]-w;
}else if(v[y]-v[x]!=w)flag=1;
}
int main(){
int w,n,m;scanf("%d",&w);
while(w--){
memset(v,0,sizeof v);
flag=0;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int x,y,z;scanf("%d%d%d",&x,&y,&z);
if(!flag)work(x-1,y,z);
}
if(flag)printf("false\n");else printf("true\n");
}
}
浙公网安备 33010602011771号