图算法
#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!