用prim和kruskal算法求最小生成树问题

简介: 用prim和kruskal算法求最小生成树问题

prim算法就类似与dijkstra算法从1号点到其他点的最短距离

kruskal算法是先按照边权排序,假如这条边的两个点不连通就加上这条边,假如连通了就跳过

1.最短网络

1140. 最短网络 - AcWing题库

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int w[N][N];
bool st[N];
int dist[N];
int n,res=0;
void prim()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;//初始化第一个点到自己的距离为0
    for(int i=1;i<=n;i++)//找剩下的n个点与第一起点的距离,就像dijkstra一样
    {
        int t=-1;
        for(int j=1;j<=n;j++)
            if(!st[j]&&(t==-1||dist[t]>dist[j]))//找不在连通块且距离最小的点
                 t=j;
        st[t]=true;//标记这个点在连通块内
        res+=dist[t];
        for(int j=1;j<=n;j++) dist[j]=min(dist[j],w[t][j]);//用该点更新其他点的最短距离
    }
}
int main()
{
   cin>>n;
   for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
         cin>>w[i][j];
   prim();
   cout<<res<<endl;
  return 0;
}

2.局域网

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

相当于一个图中求最小生成树的问题

prim解决

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int w[N][N];
bool st[N];
int dist[N];
int n,res=0,m;
void prim()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;//初始化第一个点到自己的距离为0
    for(int i=1;i<=n;i++)//找剩下的n个点与第一起点的距离,就像dijkstra一样
    {
        int t=-1;
        for(int j=1;j<=n;j++)
            if(!st[j]&&(t==-1||dist[t]>dist[j]))//找不在连通块且距离最小的点
                 t=j;
        st[t]=true;//标记这个点在连通块内
        res+=dist[t];
        for(int j=1;j<=n;j++) dist[j]=min(dist[j],w[t][j]);//用该点更新其他点的最短距离
    }
}
int main()
{
    int ans=0;
   cin>>n>>m;
   memset(w,0x3f,sizeof w);
   while(m--)
   {
      int a,b,c;
      cin>>a>>b>>c;
      w[a][b]=w[b][a]=min(w[a][b],c);
      ans+=w[a][b];//记录所有网线的答案
   }
   prim();
   cout<<ans-res<<endl;//输出总的减最小生成数的
  return 0;
}

kruskal解决

#include<bits/stdc++.h>
using namespace std;
const int N=110,M=N*N;
int n,m;
struct Edge
{
    int a,b,w;
    bool operator < (const Edge&t)const//重载小于号,待会排序就按照w排序
    {
        return w<t.w;
    }
}e[M];//结构体存数
int p[N];
int find(int x)//并查集
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
int main()
{
   int ans=0;
   cin>>n>>m;
   for(int i=1;i<=n;i++) p[i]=i;//并查集初始化
   for(int i=0;i<m;i++)
   {
       int a,b,w;
       cin>>a>>b>>w;
       e[i]={a,b,w};
   }
   sort(e,e+m);//先排序
   for(int i=0;i<m;i++)
   {
       int a=find(e[i].a),b=find(e[i].b),w=e[i].w;
       if(a!=b) p[a]=b;//假如不在一个集合,则加上该条边
       else ans+=w;//反之该条边就是多余不要的加上答案里
   }
   cout<<ans<<endl;//输出总的减最小生成数的
  return 0;
}

3.繁忙的都市

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

#include<bits/stdc++.h>
using namespace std;
const int N=310,M=N*N;
struct Edge
{
    int a,b,w;
    bool operator < (const Edge&t) const//重载小于号,使排序按照w排
    {
        return w<t.w;
    }
}e[M];
int p[N];
int find(int x)//并查集
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
int main()
{
   int n,m,ans;
   cin>>n>>m;
   for(int i=0;i<m;i++)
   {
       int a,b,w;
       cin>>a>>b>>w;
       e[i]={a,b,w};
   }
   for(int i=1;i<=n;i++) p[i]=i;//并查集初始化操作
   sort(e,e+m);//排序
   for(int i=0;i<m;i++)
   {
       int a=find(e[i].a),b=find(e[i].b),w=e[i].w;
       if(a!=b)//假如不在一个连通块中,则加上他
       {
           p[a]=b;
           ans=w;//更新最大值
       }
   }
   cout<<n-1<<' '<<ans<<endl;
  return 0;
}

4.联络员

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

这题只能用kruskal,因为有多个连通块,而prim只能处理一个连通块

#include<bits/stdc++.h>
using namespace std;
const int N=2010,M=1e4+10;
int res=0;
struct Edge
{
    int a,b,w;
    bool operator <(const Edge&t)const//重载小于号
    {
        return w<t.w;
    }
}e[M];
int p[N];
int find(int x)//并查集
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
int main()
{
  int n,m,cnt=0;
  cin>>n>>m;
  for(int i=1;i<=n;i++) p[i]=i;//初始化
  for(int i=0;i<m;i++)
  {
      int t,a,b,w;
      cin>>t>>a>>b>>w;
      if(t&1)//假如是必选
      {
          res+=w;//则加上边权
          a=find(a),b=find(b);
          p[a]=b;//加到同一个连通块中
      }
      else e[cnt++]={a,b,w};//否则非必选
  }
  sort(e,e+cnt);//排序
  for(int i=0;i<cnt;i++)
  {
      int a=find(e[i].a),b=find(e[i].b),w=e[i].w;
      if(a!=b)//假如不在一个连通块
      {
          res+=w;//则加上边权
          p[a]=b;//加到同一个连通块中
      }
  }
  cout<<res<<endl;
  return 0;
}

5.连接格点

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

就是给你已经连接了的点,让你加上某些边使他连通,也就是最小生成树,但是不能用prim,可能给出的边有环,只能用kruskal

#include<bits/stdc++.h>
using namespace std;
const int N=1010,M=N*N,K=2*M;
int ids[N][N];//用来将坐标映射到点
int n,m,k;
struct Edge
{
    int a,b,w;
}e[K];
int p[M];
int find(int x)//并查集
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
void edge()
{
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1},dw[4]={1,2,1,2};//四个方向
    for(int s=0;s<2;s++)//s表示余数,0表示打横走,1表示纵着走
        for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
             for(int u=0;u<4;u++)
                if(u%2==s)//走的途径
               {
                    int x=i+dx[u],y=j+dy[u],w=dw[u];
                    if(x<=0||x>n||y<=0||y>m) continue;//假如越界
                    int a=ids[i][j],b=ids[x][y];//获取当前位置
                    if(a<b) e[k++]={a,b,w};//为了避免重复假如
               }
}
int main()
{
  cin>>n>>m;
  for(int i=1;i<=n*m;i++) p[i]=i;//初始化
  for(int i=1,t=1;i<=n;i++)//映射坐标为点
    for(int j=1;j<=m;j++,t++)
        ids[i][j]=t;
  int x1,x2,y1,y2;
  while(cin>>x1>>y1>>x2>>y2)
  {
      int a=ids[x1][y1],b=ids[x2][y2];
      p[find(a)]=find(b);//假如是连通块了,则加到同个连通块中
  }
  edge();//处理每个走的方式
  int res=0;
  for(int i=0;i<k;i++)
  {
      int a=find(e[i].a),b=find(e[i].b),w=e[i].w;
      if(a!=b)//假如不在一个连通块
      {
          res+=w;//则加上边权
          p[a]=b;//加到同一个连通块中
      }
  }
  cout<<res<<endl;
  return 0;
}
相关文章
|
3月前
|
算法 决策智能
基于prim算法求出网络最小生成树实现网络社团划分和规划
该程序使用MATLAB 2022a版实现路线规划,通过排序节点权值并运用Prim算法生成最小生成树完成网络规划。程序基于TSP问题,采用遗传算法与粒子群优化算法进行路径优化。遗传算法通过编码、选择、交叉及变异操作迭代寻优;粒子群优化算法则通过模拟鸟群觅食行为,更新粒子速度和位置以寻找最优解。
|
5月前
|
机器学习/深度学习 算法 Java
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
这篇文章介绍了基于贪婪技术思想的Prim算法和Dijkstra算法,包括它们的伪代码描述、Java源代码实现、时间效率分析,并展示了算法的测试用例结果,使读者对贪婪技术及其应用有了更深入的理解。
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
|
6月前
|
存储 传感器 算法
|
6月前
|
机器学习/深度学习 人工智能 算法
|
7月前
|
算法 Java
Java数据结构与算法:贪心算法之最小生成树
Java数据结构与算法:贪心算法之最小生成树
|
7月前
|
算法 C语言
数据结构与算法——最小生成树问题(什么是最小生成树、Prim算法、Kruskal算法)
数据结构与算法——最小生成树问题(什么是最小生成树、Prim算法、Kruskal算法)
42 0
|
12天前
|
机器学习/深度学习 算法
基于改进遗传优化的BP神经网络金融序列预测算法matlab仿真
本项目基于改进遗传优化的BP神经网络进行金融序列预测,使用MATLAB2022A实现。通过对比BP神经网络、遗传优化BP神经网络及改进遗传优化BP神经网络,展示了三者的误差和预测曲线差异。核心程序结合遗传算法(GA)与BP神经网络,利用GA优化BP网络的初始权重和阈值,提高预测精度。GA通过选择、交叉、变异操作迭代优化,防止局部收敛,增强模型对金融市场复杂性和不确定性的适应能力。
145 80
|
5天前
|
机器学习/深度学习 算法
基于遗传优化的双BP神经网络金融序列预测算法matlab仿真
本项目基于遗传优化的双BP神经网络实现金融序列预测,使用MATLAB2022A进行仿真。算法通过两个初始学习率不同的BP神经网络(e1, e2)协同工作,结合遗传算法优化,提高预测精度。实验展示了三个算法的误差对比结果,验证了该方法的有效性。
|
8天前
|
机器学习/深度学习 数据采集 算法
基于PSO粒子群优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目展示了基于PSO优化的CNN-GRU-SAM网络在时间序列预测中的应用。算法通过卷积层、GRU层、自注意力机制层提取特征,结合粒子群优化提升预测准确性。完整程序运行效果无水印,提供Matlab2022a版本代码,含详细中文注释和操作视频。适用于金融市场、气象预报等领域,有效处理非线性数据,提高预测稳定性和效率。
|
4天前
|
算法
基于梯度流的扩散映射卡尔曼滤波算法的信号预处理matlab仿真
本项目基于梯度流的扩散映射卡尔曼滤波算法(GFDMKF),用于信号预处理的MATLAB仿真。通过设置不同噪声大小,测试滤波效果。核心代码实现数据加载、含噪信号生成、扩散映射构建及DMK滤波器应用,并展示含噪与无噪信号及滤波结果的对比图。GFDMKF结合非线性流形学习与经典卡尔曼滤波,提高对非线性高维信号的滤波和跟踪性能。 **主要步骤:** 1. 加载数据并生成含噪测量值。 2. 使用扩散映射捕捉低维流形结构。 3. 应用DMK滤波器进行状态估计。 4. 绘制不同SNR下的轨迹示例。

热门文章

最新文章