求最小生成树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)

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

相关推荐
小小怪7502 小时前
高性能密码学库
开发语言·c++·算法
Book思议-2 小时前
【数据结构实战】 C 语言单链表通关:初始化 / 头插 / 尾插 / 增删改查全实现(附图解、可运行完整代码)
c语言·数据结构·算法
2301_821700532 小时前
模板代码生成工具
开发语言·c++·算法
wuhen_n2 小时前
回溯算法入门 - LeetCode经典回溯算法题
前端·javascript·算法
宵时待雨2 小时前
C++笔记归纳12:二叉搜索树
开发语言·数据结构·c++·笔记·算法
炎爆的土豆翔2 小时前
SIMD常见操作,结合样例一文理解
开发语言·c++·算法
仰泳的熊猫2 小时前
题目2305:蓝桥杯2019年第十届省赛真题-等差数列
数据结构·c++·算法·蓝桥杯
ん贤2 小时前
Go map 底层原理
算法·golang·map
奔跑吧邓邓子2 小时前
Hash算法性能优化:从理论到实战的飞跃
算法·性能优化·哈希算法·hash·理论到实战