图算法

#include<iostream>
using namespace std;
//贪心法求单源最短路径
template<class Type>

void Dijkstra(int n,int v,Type dist[],int prev[],Type **c)
{
bool s[maxint];
for(int i=1;i<=n;i++) //以V为出发点,初始化dist[i],s[i]和prev[i]的值
{

dist[i]=c[v][i];
s[i]=false;
if(dist[i]==maxint)
prev[i]=0;
else prev[i]=v;
}
dist[v]=0;s[v]=true;
for(int i=1;i<n;i++) //共有n个点
{

int temp=maxint;
int u=v;
for(int j=1;j<=n;j++) //寻找到达所有路径点的最少值,这个是贪心算法的体现,选取最少值进行下一次的寻找
if((!s[j])&&(dist[j]<temp)

{
u=j;temp=dist[j];
}
s[u]=true; //再以它为出发点
for(int j=1;j<=n;j++)

if((!s[j])&&(c[u][j]<maxint))
{
Type newdist=dist[u]+c[u][j];
if(newdist<dist[j]) //更新其它所有的值
{

dist[j]=newdist;
prev[j]=u;
}
}
}
}

//Prim算法解决最少生成树
template<class Type>

void Prim(int n,Type **c)
{
Type lowcost[maxint]; //存储到各点的最短距离
int closest[maxint]; //存储在S中的邻接顶点
bool s[maxint];

s[1]=true;
for(int i=2;i<=n;i++) //初始化,以1为出发点
{

lowcost[i]=c[1][i];
closet[i]=1;
s[i]=false;
}
for(int i=1;i<n;i++) //共有n个顶点
{

Type min=inf;
int j=1;
for(int k=2;k<=n;k++) //全局比较,找出最少的lowcost,然后设为closet[j];
if((lowcost[k]<min)&&(!s[k]))

{
min=lowcost[k];j=k;
}
cout<<j<<''<<closet[j]<<endl;
s[j]=true; //作为下一个出发点
for(int k=2;k<=n;k++)

if((c[j][k]<lowcost[k])&&(!s[k])) //更新它于未访问集合的最短距离
{

lowcost[k]=c[j][k];
closet[k]=j;
}
}
}

//Kruskal算法构建最少生成树
template<class Type>

class EdgeNode
{
friend ostream &operator<<(ostream&,EdgeNode<Type>);
friend bool Kruskal(int ,int,EdgeNode<Type>*,EdgeNode<Type>*);
friend void main(void);
public:
operator Type() const
{
return weight;
}
private:
Type weight;
int u,v;
};

template<class Type>
bool Kruskal(int n,int e,EdgeNode<Type> E[],EdgeNode<Type> t[])
{
MinHeap<EdgeNode<Type>> H(1); //最少堆实现边的排序
H.Initialize(E,e,e);

UnionFind U(n); //用抽象数据类型并查集UnionFind
int k=0;

while(e&&k<n-1)
{
EdgeNode<int> x;
H.DeleteMin(x);
e--;
int a=U.Find(x.u); //返回U中包含顶点u的连通分支的名字
int b=U.Find(x.v);

if(a!=b)
{
t[k++]=x;
U.Union(a,b); //将U中两个连通分支a和b连接起来
}

}
H.Deactivate();
return (k==n-1);
}

//优先队列式分支界限法解决单源最短路径问题
template<class Type>

class Graph
{
friend void main(void);
public:
void ShortestPaths(int);
private:
int n, //图G的顶点数
*prev; //前驱顶点数组
Type **c, //图G的邻接矩阵
*dist; //最短距离数组
};


template<class Type>
class MinHeapNode
{
friend Graph<Type>;
public:
operator int() const
{
return length;
}
private:
int i; //顶点编号
Type length; //当前路长
};


//最少堆表示活结点的优先队列
template<class Type>

void Graph<Type>::ShortestPaths(int v)
{
//定义最少堆的容量为1000
MinHeap<MinHeapNode<Type>> H(1000);

//定义初始的扩展点
MinHeapNode<Type> E;

E.i=v;
E.length=0;
dist[v]=0;
//搜索问题的解空间
while(true)

{
for(int j=1;j<=n;j++)
if((c[E.i][j]<inf)&&(E.length+c[E.i][j]<dist[j]))
{//顶点i到顶点j可达,且满足控制约束
dist[j]=E.length+c[E.i][j];

prev[j]=E.i;
//加入活结点优先队列
MinHeapNode<Type> N;

N.i =j;
N.length=dist[j];
H.Insert(N);
}
try
{
H.DeleteMin(E); //取下一个扩展点,相当于贪心法,选取最短距离作为出发点
}

catch(OutOfBounds) //优先队列空
{

break;
}
}
}

//分支界限算法与宽度优先搜索不同的是,优先队列活结点是最小堆,而宽度优先是队列(FIFO),没有优化。
//回溯法与深度优先不同的是,回溯法拥有约束和剪枝函数,使解空间有可能缩小。



Live together,or Die alone!
原文地址:https://www.cnblogs.com/hzhida/p/2354716.html