带权并查集

最开始接触并查集是在学Kruskal算法时,今天主要学了带权并查集,记录下来我的一些理解和做题套路。

首先贴大佬博客Orz:

模板代码及详解:https://blog.csdn.net/Chris_zzj/article/details/52227656

典型例题及代码:https://blog.csdn.net/tribleave/article/details/72878239

我对带权并查集的理解:

       就是并查集多了个val数组,表示i和f[i]之间的关系(可以是距离、状态等),Find函数和Union函数要对应改些内容。

我的做题思路:

       1.画数轴;2.写Find函数;3.写Union函数(我通常直接写在main中)

主要记录两道题:

1.POJ2492  A Bug's Life​​​​(种类并查集):

思路中的2、3步详解如下:

带权并查集_第1张图片

这两部分就应该是最难搞的了,然后贴AC代码:

#include
#include
#include
#include
#include
#include
using namespace std;

const int MAX=2005;
int n,m;
int f[MAX];
int val[MAX];//0:与f[i]同类,1:与f[i]不同类

int Find(int x)
{
    if(f[x]==x)
        return x;
    int tmp=f[x];
    f[x]=Find(f[x]);
    val[x]=(val[x]+val[tmp])%2;
    return f[x];
}

int main()
{
    int t;
    scanf("%d",&t);
    for(int tt=1;tt<=t;tt++)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++)
            f[i]=i,val[i]=0;
        int a,b;
        bool sign=true;
        for(int i=0;i

还有一道类似的题是POJ1182 食物链,那道题更麻烦,分为3类,但套路也差不多。

 

2.HDU3038 How Many Answers Are Wrong  (区间统计并查集):

这道题同样画数轴,写出Find函数和Union函数,更新val[x]和val[fb]。思路就不具体写了,直接贴AC代码吧:

#include
#include
#include
#include
#include
using namespace std;

const int MAX=200005;
int n,m;
int a[MAX];
int f[MAX];
int val[MAX];//保存的是f[i]到i的和,可能为负

int Find(int x)
{
    if(f[x]==x)
        return x;
    int tmp=f[x];
    f[x]=Find(tmp);
    val[x]+=val[tmp];//修改val值
    return f[x];
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0;i<=n;i++)
            f[i]=i,val[i]=0;
        int a,b,s;
        int ans=0;
        for(int i=0;i

 

你可能感兴趣的:(算法-杂)