1.最小生成树
图G的生成树是一颗包含G的所有顶点的树,树上所有有权值总和表示代价,那么在G的所有的生成树中代价最小的生成树称为图G的最小生成树,简称(MST).
图二就是图一的最小生成树。
2.普里姆算法(prim)
prim算法和Dijkstra算法类似,也是贪心法。
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
3).重复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。
代码实现上图一的最小生成树
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
class road
{
public:
int end; //边的终点
int weight; //边的长度
};
class Graph
{
public:
int v; //顶点个数
int *mark; //标记是否访问过,访问过为1,否则为0
vector<road> *adj; //邻接表
Graph(int n); //构造函数
~Graph(); //析构函数
void addEdge(int b,int e,int w); //添加边
};
Graph::Graph(int n)
{
v=n;
mark=new int[n];
adj=new vector<road>[n];
for(int i=0;i<n;i++) //初始化标记为0
mark[i]=0;
}
Graph::~Graph()
{
delete []mark;
delete []adj;
}
void Graph::addEdge(int b,int e,int w) //因为是无向图,添加双向边
{
road r1;
r1.end = e;
r1.weight = w;
adj[b].push_back(r1);
road r2;
r2.end = b;
r2.weight = w;
adj[e].push_back(r2);
}
class Dist
{
public:
int pre;
int length;
int index;
friend bool operator<(const Dist &a,const Dist &b)
{
return a.length>b.length;
}
};
void prim(Graph &g,int s) //s是起始点
{
Dist * D = new Dist[g.v]; //申请空间
for(int i=0;i<g.v;i++) //初始化
{
D[i].index = i;
D[i].length = 1<<30;
D[i].pre = s;
}
priority_queue<Dist> aqueue;
int now_node = s;
for(int i=0;i<g.v-1;i++)
{
vector<road>::iterator ii = g.adj[now_node].begin();
for(;ii!=g.adj[now_node].end();ii++) //刷新与now_node相邻的顶点的值
{
if( g.mark[ii->end] ==0 && D[ii->end].length > ii->weight )
{
D[ii->end].length = ii->weight;
D[ii->end].pre = now_node;
aqueue.push(D[ii->end]);
}
}
Dist d;
bool FOUND=false;
while(!aqueue.empty())
{
d = aqueue.top();
aqueue.pop();
if( g.mark[d.index]== 0)
{
FOUND=true;
break;
}
}
if(!FOUND) //有不可到达的顶点
break;
g.mark[now_node]=1;
now_node=d.index;
cout<<D[now_node].pre<<"->"<<D[now_node].index<<" length: "<<D[now_node].length<<endl;
}
}
int main()
{
Graph g(7);
g.addEdge(0,1,20);
g.addEdge(0,4,1);
g.addEdge(1,3,4);
g.addEdge(1,2,6);
g.addEdge(3,5,12);
g.addEdge(3,6,8);
g.addEdge(2,6,2);
g.addEdge(4,5,15);
g.addEdge(5,6,10);
prim(g,0);
return 0;
}
运行结果