求最小生成树kruskal还是prim--备战蓝桥杯版h

解决的主要是什么问题呢,我感觉其实就是连接各点所需要的最小代价之类的问题

什么时候用kruskal/prim

prim算法(二维数组实现)

其实就是点为先,以点去扩展,每次选择的是这个点扩展出边的最小值

cpp 复制代码
int prim()
{
	memset(dist,0x3f,sizeof dist);
	dist[1]=0;
	
	int res=0;
	for(int i=0;i<n;i++)//一共n个点 
	{
		int t=-1;
		//先找到最小的dist的点
		for(int j=1;j<=n;j++)
		{
			if(!st[j]&&(t==-1||dist[j]<dist[t]))
			{
				t=j;
			}
		 } 
		st[t]=true;
		
		if(i)res+=dist[t];
		//更新其他点 
		for(int j=1;j<=n;j++)
		{
			dist[j]=min(dist[j],g[t][j]);
		}
	}
	return res;
}

练习1

858. Prim算法求最小生成树 - AcWing题库

cpp 复制代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=510,INF=0x3f3f3f3f;
int n,m;
int dist[N];
bool st[N];
int g[N][N];

int prime()
{
	memset(dist,0x3f,sizeof dist);
	dist[1]=0;
	
	int res=0;
	for(int i=0;i<n;i++)
	{
		int t=-1;
		for(int j=1;j<=n;j++)
		{
			if(!st[j]&&(t==-1||dist[j]<dist[t]))
			{
				t=j;
			}
		}
		if(i&&dist[t]==INF)return INF;
		if(i)res+=dist[t];
		st[t]=true;
		 
		for(int j=1;j<=n;j++)
		{
			dist[j]=min(dist[j],g[t][j]);
		}
	}
	return res;
} 


int main()
{
	cin>>n>>m;
	memset(g,0x3f,sizeof g);
	while(m--)
	{
		int a,b,c;
		cin>>a>>b>>c;
		g[a][b]=g[b][a]=min(g[a][b],c);
	}
	int t=prime();
	if(t==INF)cout<<"impossible"<<endl;
	else cout<<t<<endl;
	return 0;
}

练习2

P1265 公路修建 - 洛谷

cpp 复制代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 5010;
const double INF = 1e18;
int n;
struct node{
    int x, y;
} q[N];
double dist[N];
bool st[N];

double distance(int x1, int y1, int x2, int y2)
{
    double dx = x1 - x2;
    double dy = y1 - y2;
    return sqrt(dx*dx + dy*dy);
}

double prim()
{
    for(int i = 1; i <= n; i++) dist[i] = INF;
    dist[1] = 0;
    double res = 0;
    
    for(int i = 1; i <= n; i++)
    {
        int t = -1;
        for(int j = 1; j <= n; j++)
        {
            if(!st[j] && (t == -1 || dist[j] < dist[t]))
                t = j;
        }
        
        st[t] = true;
        res += dist[t];
        
        for(int j = 1; j <= n; j++)
        {
            if(!st[j])
            {
                double d = distance(q[t].x, q[t].y, q[j].x, q[j].y);
                if(d < dist[j])
                    dist[j] = d;
            }
        }
    }
    return res;
}

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> q[i].x >> q[i].y;
    }
    
    double res = prim();
    printf("%.2f\n", res);
    
    return 0;
}

练习3

P1340 [IOI 2003] 兽径管理 - 洛谷

cpp 复制代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=210,INF=0x3f3f3f3f;

int n,w;
int g[N][N];
int dist[N];
bool st[N];

int prime()
{
	memset(dist,0x3f,sizeof dist);
	memset(st,0,sizeof st);
	dist[1]=0;
	int res=0;
	for(int i=0;i<n;i++)
	{
		int t=-1;
		for(int j=1;j<=n;j++)
		{
			if(!st[j]&&(t==-1||dist[j]<dist[t]))
			{
				t=j;
			}
		}
		if(i&&dist[t]==INF)return -1;
		if(i)res+=dist[t];
		st[t]=true; 
		for(int j=1;j<=n;j++)
		{
			dist[j]=min(dist[j],g[t][j]);
		 } 
	}
	return res;
} 

int main()
{
	cin>>n>>w;
	memset(g,0x3f,sizeof g);
	for(int i=1;i<=w;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		g[a][b] = g[b][a] = min(g[a][b], c);
		int res=prime();
		cout<<res<<endl;
	}
	return 0;
}

kruskal算法(大部分题目)

先找最小边依次将最小边加入

cpp 复制代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100010;
const int M=200010;
int p[N];
int n,m;
struct EDGE
{
    int a,b,w;
}edge[M];
//并查集找父节点
int find(int x)
{
    if(p[x]!=x)p[x]=find(p[x]);
    return p[x];
}
//结构体排序函数
bool cmp(EDGE a,EDGE b)
{
    return a.w<b.w;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int x,y,c;
        cin>>x>>y>>c;
        edge[i].a=x;
        edge[i].b=y;
        edge[i].w=c;
    }
    //按照权重从小到大排序
    sort(edge,edge+m,cmp);
    //并查集初始化
    for(int i=0;i<n;i++)p[i]=i;
    //res是权重,cnt是边的条数
    int res=0,cnt=0;
    //kruskal算法:从最小的边开始画,直到把整个图画通。
    for(int i=0;i<m;i++)
    {
        int a=edge[i].a;
        int b=edge[i].b;
        int w=edge[i].w;
        a=find(a),b=find(b);
        if(a!=b)
        {
            p[a]=b;
            res+=w;
            cnt++;
        }
    }
    if(cnt<n-1)cout<<"impossible"<<endl;
    else cout<<res<<endl;
    return 0;
}

练习题(题单里的题目大部分都ok)

最小生成树专题 - 题单 - 洛谷 | 计算机科学教育新生态

相关推荐
airuike1232 分钟前
高性能MEMS IMU:重构无人机飞行控制核心
人工智能·算法·重构·无人机
娇娇爱吃蕉蕉.7 分钟前
类和对象的默认成员函数
c语言·开发语言·c++·算法
人道领域10 分钟前
【LeetCode刷题日记】哈希表:从0基础到实战全解析
算法·leetcode·哈希算法
py有趣10 分钟前
力扣热门100题之矩阵置零
算法·leetcode·矩阵
蚂蚁在飞-13 分钟前
Go 1.26
算法
汀、人工智能8 小时前
[特殊字符] 第21课:最长有效括号
数据结构·算法·数据库架构·图论·bfs·最长有效括号
Boop_wu9 小时前
[Java 算法] 字符串
linux·运维·服务器·数据结构·算法·leetcode
故事和你919 小时前
洛谷-算法1-2-排序2
开发语言·数据结构·c++·算法·动态规划·图论
Fcy64810 小时前
算法基础详解(三)前缀和与差分算法
算法·前缀和·差分
kvo7f2JTy10 小时前
基于机器学习算法的web入侵检测系统设计与实现
前端·算法·机器学习