推荐一个博客:https://blog.csdn.net/tribleave/article/details/72878239 并查集和带权并查集
带权并查集:在并查集的基础上,对其中的每一个元素赋有某些值。在对并查集进行路径压缩和合并操作时,这些权值具有一定属性,即可将他们与父节点的关系,变化为与所在树的根结点关系。
带权并查集习题:
1.(POJ1182)http://poj.org/problem?id=1182
推荐几个讲解详细的博客:https://blog.csdn.net/niushuai666/article/details/6981689 从向量的角度看问题
分析:难点在于:A.路径压缩时的关系域的更新
B.条件判断时,若两个点的根节点不同则合并;若根节点相同则按照当前给定关系与原本的关系进行判断。
总的来说就是两点之间的偏移量大小的确定
注意:改组只有一组,多组读入会WA
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=5e4+10; 6 struct node{ 7 int pre; 8 int realtion; 9 }f[maxn]; 10 11 int find(int x) 12 { 13 if ( !f[x].pre ) return x; 14 int tmp=f[x].pre; 15 f[x].pre=find(tmp); 16 f[x].realtion=(f[x].realtion+f[tmp].realtion)%3; 17 return f[x].pre; 18 } 19 20 int main() 21 { 22 int n,k,op,a,b,rt1,rt2,ans; 23 scanf("%d%d",&n,&k); 24 ans=0; 25 memset(f,0,sizeof(f)); 26 for ( int i=1;i<=k;i++ ) 27 { 28 scanf("%d%d%d",&op,&a,&b); 29 if ( a>n || b>n ) 30 { 31 ans++; 32 continue; 33 } 34 if ( op==2 && a==b ) 35 { 36 ans++; 37 continue; 38 } 39 rt1=find(a); 40 rt2=find(b); 41 if ( rt1!=rt2 ) 42 { 43 f[rt2].pre=rt1; 44 f[rt2].realtion=(f[a].realtion+op-1+3-f[b].realtion)%3; 45 } 46 else 47 { 48 if ( op==1 && f[a].realtion!=f[b].realtion ) 49 { 50 ans++; 51 continue; 52 } 53 if ( op==2 && ((3-f[a].realtion+f[b].realtion)%3!=1) ) 54 { 55 ans++; 56 continue; 57 } 58 } 59 } 60 printf("%d\n",ans); 61 return 0; 62 }