AcWing算法提高课 最小生成树

一般使用kruskal(克鲁斯卡尔)(mlogm)

对于稀疏图,用朴素prim(n^2)

prim:每次选择和当前已经构建出的连通块相连,且权重最小的边,加入当前连通块。

一共需要扩展(n-1)次

只能处理一个连通块,不能“生成森林”

 

 例题:https://www.acwing.com/problem/content/1142/

模板:

复制代码
int n;
const int N=110;
int adj[N][N];
int dis[N];
bool st[N];

int Prim()
{
    int res=0;
    memset(dis,0x3f,sizeof(dis));
    dis[1]=0;

    for(int i=0;i<n;i++)
    {
        int t=-1;
        for(int j=1;j<=n;j++)
        {
            if(!st[j]&&(t==-1||dis[t]>dis[j]))
            {
                t=j;
            }
        }
        res+=dis[t];
        st[t]=true;
        for(int j=1;j<=n;j++)
        {
            dis[j]=min(dis[j],adj[t][j]);
        }
    }
    return res;
}
View Code
复制代码

 

 kruskal:基于并查集。先将所有边从小到大排序,然后枚举每条边,如果边的两个端点还不联通,则将当前边加入最小生成树。

例题:

https://www.acwing.com/problem/content/1143/

模板:

复制代码
vector<PIII> edges;
int p[N];
int find(int x)
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
void merge(int a,int b)
{
    int pa=find(a);
    int pb=find(b);
    p[pa]=pb;
}
void Kruskal()
{
    fore(i,1,n) p[i]=i;
    sort(edges.begin(),edges.end());
    for(auto edge:edges)
    {
        int a=edge.se.fi;
        int b=edge.se.se;
        int pa=find(a);
        int pb=find(b);
        if(pa!=pb)
        {
            //record edge
            merge(a,b);
        }
    }
    
}
View Code
复制代码

 

posted @   80k  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示