模板【kruskal】

PART1

1.实现:

将每条边按权值从小到大进行排序

(要用并查集维护)容边上两点不在同一个树,则合并

2.时间复杂度:

Kruskal 算法的时间复杂度由排序算法决定,若采用快排则时间复杂度为 O(Elog⁡E)

总时间复杂度为 O(ElogE+V α(V)) 【α(V)近似看作常数】

3.特别优势:

1.prim只能用在连结成一个总集合的情况,如果是k个集合,那就只能用Kruskal

2.kruskal算法不需要建图,只需要用并查集

4.适用情况:

5.需要注意的点:

PART2

 可用代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<iomanip>
#include<iostream>
using namespace std;
const int N = 5e3+10;
const int M = 2e5+10;
#define inf 0x3f3f3f3f

//kruskalEdge
struct kruskalEdge
{
    int u, v, w;
} kE[M];
//MergeFindSet
int fa[N];
int Get(int x)
{
    if(fa[x] == x)
        return x;
    return fa[x] = Get(fa[x]);
}
inline void MergeFindSetInit(int &n)
{
    for(int i = 1; i<= n; i++)
        fa[i] = i;
}
bool Merge(int u, int v)
{
    int fu = Get(u);
    int fv = Get(v);
    if(fu != fv)
    {
        fa[fv] = fu;
        return true;
    }
    else
        return false;
}
//Kruskal
bool KruskalCmp(kruskalEdge a, kruskalEdge b)
{
    return a.w < b.w;
}
int Kruskal(int n, int m)
{
    int sum = 0;
    MergeFindSetInit(n);
    sort(kE+1, kE+m+1, KruskalCmp);
    int cnt = 0;//记录合并了多少次
    for(int i = 1; i <= m; i++)
    {
        if(Merge(kE[i].u, kE[i].v))
        {
            cnt++;
            sum += kE[i].w;
        }
    }
    if(cnt == n-1)
        return sum;
    else
        return -1;
}
//in
inline void KruskalIn(int &n, int &m)
{
    cin >> n >> m;
    for(int i = 1; i <= m; i++)
    {
        cin >> kE[i].u >> kE[i].v >> kE[i].w;
    }
}
int main()
{
    //freopen("in.txt","r", stdin);
    //freopen("out.txt","w", stdout);
    ios::sync_with_stdio(false);
    int n, m;
    KruskalIn(n, m);
    int ans = Kruskal(n, m);
    if(ans == -1)
        cout <<"no answer";
    else
        cout << ans << endl;
    return 0;
}
View Code

 

PART3

 

1.例题1:次小生成树

给定一个无向连通图,求出它的边权总和第二小的生成树。

解法:枚举最小生成树上的 n 条边,对于其中某条边,从图中删除它以后计算剩余图的最小生成树,一共 n−1棵。

从这 n−1 棵生成树中找出最小的一棵,就是整个图的次小生成树。

 

2.例题 2:边权极差最小生成树

给定一个无向连通图,求出它所有生成树中,最大边权和最小边权之差最小的生成树。

解法:利用例题 1 中给出的性质,枚举生成树上的最小边权 min_w,计算边权最小为 min_w的最小生成树,用当前最小生成树的最大边减去最小边来更新最终答案。

PART4

 

PART5

口袋天空

posted @ 2021-06-30 11:28  bear_xin  阅读(54)  评论(0编辑  收藏  举报