POJ1258 基础最小生成树

来源:互联网 发布:修真的电脑程序员txt 编辑:程序博客网 时间:2024/05/24 00:58

本文出自:http://blog.csdn.net/svitter


题意:给出一个数字n代表邻接矩阵的大小,随后给出邻接矩阵的值。输出最小生成树的权值。

题解:

prime算法的基本解法;

1.选择一个点,然后不停的向其中加入权值最小的边,边的一端在已经生成的部分生成树中,另一端在未生成的生成树中。

2.利用优先队列维护边,将加入的点所包含的边加入到队列中去,随后按照边的权值弹出。

简单理解方法:一个人可以拉很多人,新被拉进来的人,把能拉的人(有边,且未被访问)排队,找最好拉的人拉进来,循环。

注意:

1.如果使用priority_queue(二叉堆)+prime算法,时间复杂度为ElogV

2.直接使用邻接矩阵,复杂度为O(n^2)

3.使用STL 优先队列的时候记得定义排序方法;(见代码:14行)

4.记得清空vector数组


Kruskal算法的基本解法:

1.Kruskal算法存的是边。将所有边存起来,然后按照从小到大排序,依次加入两端不再同一集合的边。

2.复杂度为O(ElogE)

3.稀疏图

简单理解方法:几个人抱团,最后在全都拉在一起。

树的特点:边的个数是n-1,所以加入n-1条边即可停止。



Prime+堆解法——代码:

#include <iostream>#include <cstdio>#include <vector>#include <queue>#define INF 0xffffffusing namespace std;struct Edge{    int v;    int w;    Edge(int v_, int w_):v(v_), w(w_){}    bool operator < (const Edge &e) const    {        return w > e.w;    }};typedef vector <Edge> vedge;vector <vedge> g(110);int n;int Prime(vector <vedge> & g){    int i, j, k;    vector <int> visit(n);    vector <int> dist(n);    priority_queue <Edge> pq;    for(i = 0; i < n; i++)    {        visit[i] = 0;        dist[i] = INF;    }        Edge temp(0, 0);        int nOwn = 0;    int nWeight = 0;    pq.push(Edge(0, 0));    while(nOwn < n && !pq.empty())    {        do        {            temp = pq.top();            pq.pop();        }        while(visit[temp.v] == 1 && !pq.empty());        if(visit[temp.v] == 0)        {            nOwn++;            nWeight += temp.w;            visit[temp.v] = 1;        }        for(i = 0 ; i < g[temp.v].size(); i++)        {            int v = g[temp.v][i].v;            if(visit[v] == 0)            {                int w = g[temp.v][i].w;                dist[v] = w;                pq.push(Edge(v, w));            }        }    }    if(nOwn < n)    {        cout << nOwn << n << endl;        return -1;    }    return nWeight;}int main(){     int i, j, k;    int temp;    while(~scanf("%d", &n))    {        for(i = 0; i < n; i++)            g[i].clear();        for(i = 0; i < n; i++)            for(j = 0; j < n; j++)            {                scanf("%d", &temp);                g[i].push_back(Edge(j, temp));            }                cout << Prime(g) << endl;    }    return 0;}

Kruscal算法代码:

//author: svtter//#include <algorithm>#include <vector>#include <iostream>#include <stdio.h>#include <string.h>const int MAXN = 100000;using namespace std;vector <int> root;int n;struct Edge{    int i, j, w;    Edge(int i_, int j_, int w_):i(i_), j(j_), w(w_){}    bool operator < (const Edge &e) const    {        return w < e.w;    }};void init(){    for(int i = 0; i < n; i++)        root.push_back(i);}int getRoot(int i){    if(root[i] == i)        return i;    return root[i] = getRoot(root[i]);}void Merge(int i, int j){    int a, b;    a = getRoot(i);    b = getRoot(j);    if(a == b)        return;    //a's root is a;    root[a] = b;}vector <Edge> g;int Kruskal(){    //init the    init();    sort(g.begin(),g.end());    //the num of tree's Edges is n-1;    //    int nEdge = 0;    //the weight of whole gtree    int nWeight = 0;    int i, s, e, w;    for(i = 0; i < g.size(); i++)    {        s = g[i].i;        e = g[i].j;        w = g[i].w;        if(getRoot(s) != getRoot(e))        {            Merge(s,e);            nWeight += w;            nEdge++;        }        if(nEdge == n-1)            break;    }    return nWeight;}int main(){    int i, j, k;    while(~scanf("%d", &n))    {        g.clear();        root.clear();        for(i = 0; i < n ; i++)            for(j = 0; j < n; j++)            {                scanf("%d", &k);                g.push_back(Edge(i, j, k));            }        cout << Kruskal() << endl;    }    return 0;}


0 0
原创粉丝点击