题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102

题意:给出任意两个城市之间建一条路的时间,给出哪些城市之间已经建好,问最少还要多少时间使所有的城市连通?

思路:已经建好的城市之间需要的时间设为0,就是求最小生成树的权值和了。

顺便复习一下prim算法。

讲道理,好像我的prim算法没有判断加入这个点是不是会产生回路?

回答:只有生成树集合里的点加入超过1次的时候,它还是要和集合里的某个点连一条边,于是就产生回路了。所以代码通过vis数组判断当前点是不是在生成树集合里

就可以判断是不是会产生回路了。

邻接表形式?

 

知道思想就可以实现,才是合格的搬砖工,希望以后脱离模板。

附代码:

/*
prim 最小生成树算法
过程:prim算法将图分为两部分,假设原顶点集为V,将其分为S和V-S两部分,S为已经确定在最小生成树上的顶点,
开始时,将任意一个顶点加入到S,然后每次在V-S中寻找距离S中的点最近的点。作为下一个加入最小生成树上的点。
所有N个节点都加入到最小生成树中时,最小生成树构造完毕。

实现:对于邻接矩阵构造的图,可以用low[N]保存每个顶点到已加入生成树中所有点的最小距离。
每次寻找这个距离最小的一个点加入最小生成树中。再根据这个点的距离更新其它未加入生成树中的点。
直到所有的点都加入到最小生成树中。
*/

// Eg:HDU 1102

#include <stdio.h>
#include <string.h>
#include <iostream>
#define inf 1000000
using namespace std;

int g[210][210];
int low[210];
int vis[210]; // 表示该点是否已经加入最小生成树中
int n;

int prim() {
    for (int i=0; i<n; ++i) {
        low[i] = g[0][i];
    }

    int ans = 0;
    memset(vis, 0, sizeof(vis));
    vis[0] = 1;

    for (int i=1; i<n; ++i) { // 循环n-1次,找剩下的n-1个点。
        int k = -1, mindis = inf;
        for (int j=0; j<n; ++j) { // 循环找当前剩下的点中 距离最小生成树点集距离最短的点。
            if (!vis[j] && low[j] < mindis) {
                mindis = low[j];
                k = j;
            }
        }

         if (k == -1) return -1;
         vis[k] = 1; // 加入最小生成树点集
         ans += mindis;

         for (int j=0; j<n; ++j) { // 更新没加入最小生成树的点中 距离是否会缩短。
            /*if (!vis[j] && low[j] > low[k] + g[k][j]) {
                    low[j] = low[k] + g[k][j];
            }*/

             if (!vis[j] && low[j] > g[k][j]) { // 上面的if是错的。low数组存储的距离是当前点到生成树中所有点距离最小的的点。
                    low[j] = g[k][j]; // 因为这个点加入最小生成树集合中,可以和其中任意一个点连一条边。
            }
        }
    }
    return ans;
}


int main() {
    int q;
    while(cin >> n) {
        for (int i=0; i<n; ++i) {
            for (int j=0; j<n; ++j) {
                cin >> g[i][j];
            }
        }

        cin >> q;
        for (int i=0; i<q; ++i) {
            int a, b;
            cin >> a >> b;
            a--, b--;
            g[a][b] = 0;
            g[b][a] = 0;
        }

        int ans = prim();
        cout << ans << endl;
    }
    return 0;
}

  

 

posted on 2016-03-19 11:59  小小八  阅读(1238)  评论(0编辑  收藏  举报