最小生成树

本文介绍了两种常见的最小生成树构造算法——Prim算法和Kruskal算法。Prim算法通过不断选择最小距离的未加入节点,直至连接所有节点。Kruskal算法则依据边的权重进行排序,并在不形成环路的情况下逐步加入边,直到连接所有节点。代码分别展示了这两种算法的C++实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

prime模板

核心代码:
for(j = 1; j < n; j++)
   {
    if(lowcost[j] != 0 && lowcost[j] > dis[choose] [j] )
 //在这里第一条找到的边是6,那么此时的choose是2,这里的意思就是:
//原点到某一点的距离大于被标记的这一点到其余一点的距离,即使说,原点到这些点都可以更新
//也就是相当于找到2后,然后再更新的时候把1~2的边6给抽掉了,即是说把1~2这条边都当做自己的了
//咦,然后发现3变小了,成了8,哇可以更新!赶紧~~~
     lowcost[j] = dis[choose][j];
   }

 

 

 program:

#include <iostream>
#include <memory>
#include <cmath>
using namespace std;

int const MAX = 110;
int dis[MAX][MAX];
int lowcost[MAX];

int main()
{
int n;
int i,j;

while(cin >> n)
{
for(i = 0; i < n; i++)
   for(j = 0; j < n; j++)
    cin >> dis[i][j];

//下面是prim算法部分,ans是计算所有路径的和
lowcost[0] = 0;
for(i = 1; i < n; i++)
   lowcost[i] = dis[0][i];

int ans = 0;
for(i = 1; i < n; i++)
{
   double min = (1<<30);
   int choose;
   for(j = 1; j < n; j++)
   {
    if(lowcost[j] != 0 && lowcost[j] < min)
    {
     min = lowcost[j];
     choose = j;
    }
   }

   ans += lowcost[choose];
   lowcost[choose] = 0;
   for(j = 1; j < n; j++)
   {
    if(lowcost[j] != 0 && lowcost[j] > dis[choose][j])
     lowcost[j] = dis[choose][j];
   }
}
cout << ans << endl;
}
return 0;
}

kruskal模板

#include <iostream>
#include <memory>
#include <algorithm>
using namespace std;

const int MAX = 1010; //节点个数
const int MAXEDGE = 15010; //边个数
bool used[MAXEDGE]; //标记边是否用过

struct node
{
int begin, end, dis;
}data[MAXEDGE];

class UFSet
{
private:
int parent[MAX+1];
int size;
public:
UFSet(int s = MAX);
int Find(int x);
void Union(int root1, int root2);
};

UFSet::UFSet(int s)
{
size = s+1;
memset(parent, -1, sizeof(int)*size);
}
void UFSet::Union(int root1, int root2)
{
int temp = parent[root1] + parent[root2];
if(parent[root1] <= parent[root2])
{
   parent[root2] = root1; 
   parent[root1] = temp;
}
else
{
   parent[root1] = root2;
   parent[root2] = temp;
}
}
int UFSet::Find(int x)
{
int p = x;
while(parent[p] > 0)
   p = parent[p];

int t = x;
while(t != p)
{
   t = parent[x];
   parent[x] = p;
   x = t;
}
return p;
}

bool cmp(node a, node b)
{
return (a.dis < b.dis);
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
int i,j;

for(i = 0; i < m; i++)
   scanf("%d%d%d", &data[i].begin, &data[i].end, &data[i].dis);

//最小生成树
UFSet ufs(n);
sort(data, data+m, cmp);

int root1, root2;
int total = 0;
for(i = 0; i < m; i++)
{
   root1 = ufs.Find(data[i].begin);
   root2 = ufs.Find(data[i].end);
   if(root1 == root2) continue;
   ufs.Union(root1, root2);
   used[i] = true;
   total++;
   if(total == n-1) break;
}
printf("%d\n%d\n", data[i].dis, n-1);
for(j = 0; j <= i; j++)
   if(used[j])
    printf("%d %d\n", data[j].begin, data[j].end);

return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值