来复习复习最小生成树的算法,其中的prim算法比较简单。虽说用一般的邻接矩阵需要O(V2)的的时间复杂度。但是改为邻接表之后,会稍微提高到O(E log(V))。
不过,这个,测试数据输错了,把我郁闷了半个钟头。太大意了。
这个Prim算法的原理呢,和Dijkstra算法有些类似。一个小城镇的扩张,慢慢侵蚀离它最近的点,吞噬成为其一部分,然后再继续吞噬。
Wiki上给出的比较好懂,我的比较抽象了。如下:
从单一顶点开始,普里姆算法按照以下步骤逐步扩大树中所含顶点的数目,直到遍及连通图的所有顶点。
- 输入:一个加权连通图,其中顶点集合为V,边集合为E;
- 初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {};
- 重复下列操作,直到Vnew = V:
- 在集合E中选取权值最小的边(u, v),其中u为集合Vnew中的元素,而v则不是(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
- 将v加入集合Vnew中,将(u, v)加入集合Enew中;
- 输出:使用集合Vnew和Enew来描述所得到的最小生成树。
代码如下:
#include <iostream>
#include <queue>
#define MAX_VERTEX 15
#define MAX_EDGE 25
#define AL_END -1
using namespace std;
struct Edge
{
int next;
int vertex;
int cost;
};
struct Vertex
{
int cost;
int vertex;
};
bool operator <(const Vertex &a, const Vertex &b)
{
return a.cost > b.cost;
}
class AlGraph
{
public:
int smallestCost;
void prim();
private:
int vertexNum;
int edgeNum;
int AlVertex[MAX_VERTEX];
Edge edge[MAX_EDGE];
bool vertexDealed[MAX_VERTEX];
priority_queue<Vertex> primQueue;
void initialize();
void getData();
};
void AlGraph::initialize()
{
smallestCost = 0;
memset(AlVertex, AL_END,sizeof(AlVertex));
memset(vertexDealed, 0, sizeof(vertexDealed));
while (!primQueue.empty())
{
primQueue.pop();
}
}
void AlGraph::getData()
{
initialize();
cout << "Please input the vertex number: ";
cin >> vertexNum;
cout << "Please input the edge number: ";
cin >> edgeNum;
int source, destination, cost;
int ip = 0;
cout << "Please input the edges(source, destination, cost)." << endl;
for (int i = 0; i < edgeNum; i++)
{
cin >> source >> destination >> cost;
edge[ip].next = AlVertex[source];
edge[ip].cost = cost;
edge[ip].vertex = destination;
AlVertex[source] = ip++;
swap(source, destination);
edge[ip].next = AlVertex[source];
edge[ip].cost = cost;
edge[ip].vertex = destination;
AlVertex[source] = ip++;
}
}
void AlGraph::prim()
{
getData();
int gotNum = 0;
Vertex firstVertex;
firstVertex.cost = 0;
firstVertex.vertex = 0;
primQueue.push(firstVertex);
while (gotNum < vertexNum)
{
if (primQueue.empty())
{
cout << "Islet discovered!" << endl;
break;
}
Vertex nowvertex = primQueue.top();
primQueue.pop();
if (vertexDealed[nowvertex.vertex])
{
continue;
}
gotNum++;
smallestCost += nowvertex.cost;
vertexDealed[nowvertex.vertex] = true;
for (int i = AlVertex[nowvertex.vertex]; i != AL_END; i = edge[i].next)
{
if (!vertexDealed[edge[i].vertex])
{
nowvertex.cost = edge[i].cost;
nowvertex.vertex = edge[i].vertex;
primQueue.push(nowvertex);
}
}
}
}
int main()
{
AlGraph test;
test.prim();
cout << "The smallest cost is: " << test.smallestCost << endl;
return 0;
}