POJ - 1251 ( 最小生成树 )

明天就考高数了,我竟然在学算法……
新学会个最小生成树,找了个模版题试试,AC了就很开心!
这道题其实就是套模版,但是这个算法很有趣。
代码:

// 最小生成树
include <cstdio>
#include <climits>
#include <cstring>
const int maxn = 30;

int n;                                      
int road[maxn][maxn];                                    
int dis[maxn];      
int vis[maxn];

void input() {              // 注意本题输入形式
    char u[2];
    char node[2];
    int d, N;
    for(int i = 0; i < n -1 ; i++) {       
        scanf("%s%d", u, &N);
        while(N--) {
            scanf("%s%d", node, &d);
            road[u[0]-'A'][node[0]-'A'] = road[node[0]-'A'][u[0]-'A'] = d;
        }
    }
}

void prim() {                        // 用这个函数计算和打印结果,顾名思义用了prim算法……
    int min_dis;
    int v;
    int sum = 0;
    for(int i = 1; i < n; i++) {     // 一开始确定一个节点,确定该节点与其他节点的distance,如果是-1则代表不相连
        dis[i] = road[0][i];
    }
    vis[0] = 1;
    dis[0] = 0;

    int cnt = n;

    while(cnt--) {
        min_dis = INT_MAX;
        for(int j = 0; j < n; j++) {    // 找到到已遍历节点路程最短的节点
            if (!vis[j] && dis[j] != -1 && min_dis > dis[j]) {
                v = j;
                min_dis = dis[j];
            }
        }

        vis[v] = 1;          // 标记遍历过该节点

        for(int i = 0; i < n; i++) {         // 找到新加入节点与未遍历节点的关系,更新dis状态……
            if (!vis[i] && road[v][i] != -1 && (road[v][i] < dis[i] || dis[i] == -1)) {      // 这个`或`值得想一下,一种可能是之前遍历过的节点未与该节点相连,一种是路程小于以前的节点,一开始没考虑好老是过不了用例
                dis[i] = road[v][i];     
            }
        }
    }

    for(int i = 0; i < n; i++) {  
        sum += dis[i];
    }
    printf("%d\n", sum);
}

void init() {
    memset(road, -1, sizeof(road));       //把road里的值都弄成-1
    memset(vis, 0, sizeof(vis));         
    for(int i = 0; i < n; i++) {
        road[i][i] = 0;                   //节点和自己连路程当然是0喽
    }
};

int main() {
    //freopen("input.txt", "r", stdin);
    while(~scanf("%d", &n) && n) {
        init();
        input();
        prim();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunmaoxiang/article/details/80836962
今日推荐