Networking POJ-1287 题解 prim

题目链接: voj

题意

voj的翻译有时候不靠谱,如果很多翻译输入输出格式不同,记得看看原文。
边数量无限,有重边的最小生成树。

输入

多样例输入。每个样例都保证有解。
每个样例的第一行有两个整数,P(点的个数),R(点与点之间的路径总数)。
接下来的R行输入路径,每行含3个整数,前两个数表示连接的两个点,第三个数表示路径长度。
P为0时输入结束(直接没有q了)。样例与样例之间存在空行
P最大为50,路径长度最大为100,路径数没有限制
i和j之间的路径可以表示为 i j 或 j i。

输出

对于每个样例,输出一个数表示设计出的路径总长度

输入样例

1 0

2 3
1 2 37
2 1 17
1 2 68

3 7
1 2 19
2 3 11
3 1 7
1 3 5
2 3 89
3 1 91
1 2 32

5 7
1 2 5
2 3 7
2 4 8
4 5 11
3 5 10
1 5 6
4 2 12

0

输出样例

0
17
16
26

解题思路

因为边数量无限,所以必须使用prim算法。顺便一说,prim算法适用于稠密图,kruscal算法适用于稀疏图。

AC代码

#include <stdio.h>
#include <set>
#include <string.h>
#define MAX 0x3f3f3f3f
using namespace std;
const int num = 55;
int dis[num];
bool vis[num];
int map[num][num];
int n, m;

int prim()
{
    int ans = 0;
    vis[1] = true;
    for (int i = 1; i <= n; i++)
    {
        dis[i] = map[1][i];
    }
    for (int i = 0; i < n; i++)
    {
        int min = MAX, k = -1;
        for (int j = 2; j <= n; j++)
        {
            if (dis[j] < min&&!vis[j])
            {
                k = j;
                min = dis[j];
            }
        }
        vis[k] = true;
        ans += dis[k];
        for (int j = 1; j <= n; j++)
        {
            if (!vis[j] && dis[j] > map[k][j])
                dis[j] = map[k][j];
        }
    }
    return ans;
}
int main()
{

    while (scanf("%d", &n) && n != 0)
    {
        scanf("%d", &m);
        // init
        for (int i = 1; i <= n; i++)
        {
            map[i][i] = 0;
            for (int j = 1; j <= i; j++)
            {
                map[i][j] = map[j][i] = MAX;
            }
        }
        memset(vis, false, sizeof vis);
        // input
        for (int i = 0; i < m; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            if (map[a][b] > c)
            {
                map[a][b] = map[b][a] = c;
            }
        }
        printf("%d\n", prim());
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值