[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"); } }