//集合S:已计算出最短路径的集合
//集合V:未计算出最短路径的集合.
//从集合V中选出最短路径的顶点,加入集合S中,并利用刚选的最短路径更新V中的最短路径。
# include<iostream>
# include<cstring>
# include<stack>
using namespace std;
# define INF 0x3f3f3f3f
# define NIL -1
const int maxn=100+5;
struct node{
int weight; //权重
};
struct graph{
int virtexs[maxn];//顶点集
node virtex[maxn][maxn]; //邻接矩阵
int virtexnum,edgenum; //顶点数,边数.
};
stack<int> s;
graph g;
int dis[maxn]; //存储u到i的最短距离 ;
bool vis[maxn];
int predessor[maxn];//前趋数组例如predessor[v]=u表示v的前趋为u; 形成一个前趋树
void init(graph &g)
{
cin>>g.virtexnum>>g.edgenum;
for(int i=0;i<g.virtexnum;i++)
cin>>g.virtexs[i];
for(int i=0;i<g.virtexnum;i++)
{
for(int j=0;j<g.virtexnum;j++)
{
if(i==j) g.virtex[i][j].weight=0;
else
g.virtex[i][j].weight=INF;
}
predessor[i]=NIL;
}
for(int i=0;i<g.edgenum;i++)
{ int u,v,w;
cin>>u>>v>>w;
g.virtex[u-1][v-1].weight=w;
}
}
void dijkstra(int u)//时间复杂度O(n*2);
{
memset(vis,0,sizeof(vis));
for(int i=0;i<g.virtexnum;i++)
{
dis[i]=g.virtex[u-1][i].weight; //初始化
}
vis[u-1]=true; //加入集合s中
for(int j=1;j<g.virtexnum;j++)//
{
int min=INF,temp;
for(int i=0;i<g.virtexnum;i++) //从未计算 的最短路径中选择最小路径.
{
if(!vis[i]&&min>dis[i])
{
min=dis[i];
temp=i;
}
}
vis[temp]=true; //加入集合s中
for(int i=0;i<g.virtexnum;i++) //进行比较,并更行dis数组
{
if(!vis[i]&&dis[i]>dis[temp]+g.virtex[temp][i].weight)
{
dis[i]=dis[temp]+g.virtex[temp][i].weight;
predessor[i]=temp; //i的前趋为temp。
}
}
}
}
/*void print_path(int n,int i) //显式定义栈,并调用栈
{
s.push(i);
int j=predessor[i];
while(j!=-1)
{
s.push(j);
j=predessor[j];
}
while(!s.empty())
{
cout<<"->"<<s.top()+1;
s.pop();
}
}*/
void print_path(int s,int v) //递归
{
if(s==v)
{
cout<<"->"<<s+1;
}
else if(predessor[v]==NIL)
{
cout<<"->"<<v+1;
}
else{
print_path(s,predessor[v]);
cout<<"->"<<v+1;
}
}
int main()
{
int n;
cin>>n;
init(g);
dijkstra(n);
for(int i=0;i<g.virtexnum;i++)
{
if((n-1)!=i)
{
cout<<n;
print_path(n,i);
cout<<" ";
if(dis[i]==INF)
cout<<"&"<<" ";
else
cout<<dis[i]<<" ";
cout<<endl;
}
}
return 0;
}
总结:
(1)diskstra算法假定输入图中的所有边的权值非负.
(2) bfs是在无权图上执行的最短路径算法.
(4)bfs指出是否有从A到B的路径如果有,就可以找出最短路径.