最小生成树c语言(普利姆算法)

7-2 公路村村通

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:

输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。

输出格式:

输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。

输入样例:

6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3

输出样例:

12

普利姆算法基于贪心思想,每次选取生成树中节点到树外节点距离最小的节点加入生成树来扩充,直到所有节点加入生成树为止,具体实现推荐看【懒猫老师数据结构-(43)最小生成树(Prim算法的实现,普里姆算法,普利姆)】

因为没有要求各节点间关系,所以没有记录

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int max = 0x3f3f3f3f;
int findmin(int a[], int f[], int n);
int main()
{
    int n, m, id2, id, v;
    scanf("%d %d", &n, &m);
    int a[n + 1][n + 1],//邻接矩阵
     val[n + 1] = {0},//最小权值
      f[n + 1] = {0};//加入最小生成树标志
    f[1] = 1;//第一个元素加入
    memset(a, 0x3f, sizeof(a));

    for (int i = 0; i < m; i++)
    {
        scanf("%d%d%d", &id, &id2, &v);
        a[id][id2] = v;
        a[id2][id] = v;
    }
    for (int i = 1; i <= n; i++)
        val[i] = a[1][i];
    int k = findmin(val, f, n);//找到下一个加入元素
    f[k] = 1;//加入生成树
    for (int i = 1; i < n; i++)
    {
        for (int i = 1; i <= n; i++)
            if (a[k][i] < val[i] && f[i] == 0)
                val[i] = a[k][i];//找到更小路径权值
        k = findmin(val, f, n);
        f[k] = 1;
    }
    k = 0;
    for (int i = 2; i <= n; i++)
    {
        if (val[i] != max)
        {
            k += val[i];
        }
        else
        {
            printf("-1");
            return 0;
        }
    }
    printf("%d\n", k);
    // system("pause");
    return 0;
}
int findmin(int a[], int f[], int n)
{
    int i = 1;
    while (f[i] == 1)
        i++;
    int min = a[i];
    int k = i;
    for (i++; i <= n; i++)
    {
        if (a[i] < min && f[i] == 0)
        {
            min = a[i];
            k = i;
        }
    }
    return k;
}

posted @ 2023-12-15 15:52  CV小能手chh  阅读(13)  评论(0)    收藏  举报  来源