最小生成树(求的就是给定一个无向图,挑选若干条边,连成一个树行图(无圈),使得所选边的权至和最小。)
Prim:
//prim算法
int prim(int n)
{
int i,j,min,pos;
int sum=0;
memset(isvisited,false,sizeof(isvisited));
//初始化
for (i=1;i<=n;i++)
{
dist[i]=map[1][i];
}
//从1开始
isvisited[1]=true;
dist[1]=MAX;
//找到权值最小点并记录下位置
for (i=1;i<n;i++)
{
min=MAX;
//pos=-1;
for (j=1;j<=n;j++)
{
if (!isvisited[j] && dist[j]<min)
{
min=dist[j];
pos=j;
}
}
sum+=dist[pos];//加上权值
isvisited[pos]=true;
//更新权值
for (j=1;j<=n;j++)
{
if (!isvisited[j] && dist[j]>map[pos][j])
{
dist[j]=map[pos][j];
}
}
}
return sum;
}
感悟: 最小生成树的代码与地杰斯特拉有着相像之处 ,prim算法是相加的是权重而地杰斯特拉增加的是下一个边
还有一种算法和prim的代码功能相同是kruskal,但是代码量大~
地杰斯特拉(求的是从一点到另一点的最短路径)(有向图)权值不能为负值
代码:
/***************************************
* About: 有向图的Dijkstra算法实现
***************************************/
#include <iostream>
using namespace std;
const int maxnum = 100;
const int maxint = 999999;
void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
{
bool s[maxnum]; // 判断是否已存入该点到S集合中
for(int i=1; i<=n; ++i)
{
dist[i] = c[v][i];
s[i] = 0; // 初始都未用过该点
if(dist[i] == maxint)
prev[i] = 0;
else
prev[i] = v;
}
dist[v] = 0;
s[v] = 1;
// 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
// 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
for(int i=2; i<=n; ++i)
{
int tmp = maxint;
int u = v;
// 找出当前未使用的点j的dist[j]最小值
for(int j=1; j<=n; ++j)
if((!s[j]) && dist[j]<tmp)
{
u = j; // u保存当前邻接点中距离最小的点的号码
tmp