Agri-Net(POJ 1258)(裸最小生成树)(Prime算法+Kruskal算法)

来源:互联网 发布:eclipse js编辑器插件 编辑:程序博客网 时间:2024/05/19 18:43

http://acm.hust.edu.cn/vjudge/problem/10756

题意:给你n个点以及n个点中每两个点之间距离,问你连接所有节点的最小路径总长度是多少。

题解:根据最小生成树的定义可知,这道题是一道最小生成树的题。而算最小生成树的题一般有两种算法,一种是Prime,一种是Kruskal,两种都可以。下文分别给出了两种算法的代码实现(套模板)。

思考:

vector<vector<Edge>> G(110);//存图的邻接表的时候一般都这么存

Prime算法实现代码:

#include <iostream>#include <cstdio>#include <string>#include <algorithm>#include <cstring>#include <cmath>#include <vector>#include <map>#include <set>#include <queue>using namespace std;const int INF = 1 << 30;struct Edge{    int v;    int w;    Edge (int vv = 0, int ww = INF) : v(vv), w(ww) {}    bool operator <(const Edge& e) const    {        return w > e.w;    }};vector <vector <Edge> > G(110);//存图的邻接表的时候一般都这么存int HeapPrim(const vector<vector<Edge> > & G, int n){    int i, j, k;    Edge xDist(0, 0);    priority_queue<Edge> pq;    vector<int> vDist(n);    vector<int> vUsed(n);    int nDoneNum = 0;    for (i = 0; i < n; i++) {        vUsed[i] = 0;        vDist[i] = INF;    }    nDoneNum = 0;    int nTotalW = 0;    pq.push(Edge(0, 0));    while (nDoneNum < n && !pq.empty()) {        do {            xDist = pq.top();            pq.pop();        } while (vUsed[xDist.v] == 1 && !pq.empty());        if (vUsed[xDist.v] == 0) {            nTotalW += xDist.w;            vUsed[xDist.v] = 1;            nDoneNum++;            for (i = 0; i < G[xDist.v].size(); i++) {                int k = G[xDist.v][i].v;                if (!vUsed[k]) {                    int w = G[xDist.v][i].w;                    if (vDist[k] > w) {                        vDist[k] = w;                        pq.push(Edge(k, w));                    }                }            }        }    }    if (nDoneNum < n) return -1;    return nTotalW;}int main(){    #ifndef ONLINE_JUDGE    freopen ("in.txt", "r", stdin);    #endif // ONLINE_JUDGE    int n;    while (scanf ("%d", &n) != EOF) {        for (int i = 0; i < n; i++) {            G[i].clear();        }        for (int i = 0; i < n; i++) {            for (int j = 0; j < n; j++) {                int w;                scanf ("%d", &w);                G[i].push_back(Edge(j, w));            }        }        printf ("%d\n", HeapPrim (G, n));    }    return 0;}

Kruskal算法实现代码:

#include <iostream>#include <cstdio>#include <string>#include <algorithm>#include <cstring>#include <cmath>#include <vector>#include <map>#include <set>#include <queue>using namespace std;struct Edge{    int s, e, w; //起点,终点,权值    Edge(int ss, int ee, int ww) : s(ss), e(ee), w(ww) {}    Edge() {}    bool operator < (const Edge & e1) const {        return w < e1.w;    }};vector<Edge> edges;vector<int> parent;int GetRoot(int a){    if (parent[a] == a) return a;    parent[a] = GetRoot (parent[a]);    return parent[a];}void Merge(int a, int b){    int p1 = GetRoot (a);    int p2 = GetRoot (b);    if (p1 == p2) return;    parent[p2] = p1;}int main(){    int n;    while (cin >> n) {        parent.clear();        edges.clear();        for (int i = 0; i < n; i++) parent.push_back(i);        for (int i = 0; i < n; i++) {            for (int j = 0; j < n; j++) {                int w;                cin >> w;                edges.push_back(Edge(i, j, w));            }        }        sort (edges.begin(), edges.end());        int done = 0;        int totallen = 0;        for (int i = 0; i < edges.size(); i++) {            if (GetRoot (edges[i].s) != GetRoot (edges[i].e)) {                Merge (edges[i].s, edges[i].e);                done++;                totallen += edges[i].w;            }            if (done == n - 1) break;        }        cout << totallen << endl;    }    return 0;}
0 0
原创粉丝点击