返回顶部

并查集(带路径压缩)

并查集

用于快速查找集合中元素是否存在关系的数据结构,主要操作为:查询合并
并查集简述

常用的带有路径压缩版本的并查集模板:

带路径压缩的并查集在一般情况下的查询或者合并操作,其时间复杂度近似于O(1)

#define MAXN 5000
int fa[MAXN+1];
void init(int n)
{
    for(int i = 1; i <= n; i++)
    {
        fa[i] = i; //初始化
    }
}

int find(int x)
{
    if(fa[x]==x)
        return x;
    return fa[x] = find(fa[x]); //查询时进行路径压缩
}

void merge(int x, int y)
{
    fa[find(x)] = find(y); //合并
}

实战1:P1111修复公路



思路:这题本质要求我们权为时间t的图的最小生成树,具体做法为:先将边按时间从小到大排序,然后依次判断取边,当构成生成树(下为ans==n-1)时即输出答案即可

赋AC代码:

#include <stdio.h>
#include <stdlib.h>
#define MAXN 1000
int fa[MAXN+1];
typedef struct maye
{
    int u, v, t;
}ccc;
void init(int n)
{
    for(int i = 1; i <= n; i++)
    {
        fa[i] = i; //初始化
    }
}

int find(int x)
{
    if(fa[x]==x)
        return x;
    return fa[x] = find(fa[x]); //查询时进行路径压缩
}

void merge(int x, int y)
{
    fa[find(x)] = find(y); //合并
}

int com(const void *a, const void *b)
{
    return (*(ccc *)a).t - (*(ccc *)b).t;
}
int main(void)
{
    int n, m, ans = 0;
    scanf("%d %d",&n,&m);
    init(n);
    ccc path[m+1];
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d %d",&path[i].u,&path[i].v,&path[i].t);
    }
    qsort(path+1, m, sizeof(ccc), com);
    for(int i = 1; i <= m; i++)
    {
        if(find(path[i].u)!=find(path[i].v))
            ans++;
        merge(path[i].u, path[i].v);
        if(ans==n-1)
        {
            printf("%d\n",path[i].t);
            return 0;
        }
    }
    printf("-1\n");
    return 0;
}

实战2:P1195口袋的天空


思路:与上一题类似,同样将边按权从小到大排序,初始集合总数为n,然后对于每一条边,如果不连通,就选上并更新连通性(如果不用选就直接跳过),这样集合总数会-1,直到集合数为k时得到答案

赋AC代码:

#include <stdio.h>
#include <stdlib.h>
#define MAXN 1000
int fa[MAXN+1];
typedef struct maye
{
    int u, v, l;
}ccc;
void init(int n)
{
    for(int i = 1; i <= n; i++)
    {
        fa[i] = i; //初始化
    }
}

int find(int x)
{
    if(fa[x]==x)
        return x;
    return fa[x] = find(fa[x]); //查询时进行路径压缩
}

void merge(int x, int y)
{
    fa[find(x)] = find(y); //合并
}

int com(const void *a, const void *b)
{
    return (*(ccc *)a).l - (*(ccc *)b).l;
}
int main(void)
{
    int n, m, ans, k, answer = 0;
    scanf("%d %d %d",&n,&m,&k);
    ans = n;
    init(n);
    ccc path[m+1];
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d %d",&path[i].u,&path[i].v,&path[i].l);
    }
    qsort(path+1, m, sizeof(ccc), com);
    for(int i = 1; i <= m; i++)
    {
        if(find(path[i].u)==find(path[i].v))
            continue;
        merge(path[i].u, path[i].v);
        ans--;
        answer+=path[i].l;
        if(ans==k)
        {
            printf("%d\n",answer);
            return 0;
        }
    }
    printf("No Answer\n");
    return 0;
}

posted on 2019-12-11 14:47  进击の辣条  阅读(262)  评论(0编辑  收藏  举报

导航