- dijkstral算法:计算单源最短路径(固定起点,计算出起点到其他所有顶点的最短路径)
- 用贪心思想,每次找出距离起点最近的节点,直到找出所有节点
- 动态规划:每次在已有结果的基础上自下而上进行拓展
- 缺陷:无法计算存在负权值的情况。
- floyd算法:计算任意两点之间的最短路径
- 基于动态规划思想
- 三重循环遍历所有顶点,如果a到c再到b的距离,小于a到b的距离,那么将a到b原来的路径更换为a到c再到b
- 其中路径信息parent矩阵,
parent[i][j]
代表的是,从i到j,i走过以后,下一步应该走哪个节点,如果parent[i][j]==j
说明i、j相邻。
/*Dijkstra算法,用于解决单源最短路径问题(src到任意点的最短路径)
* 思路:如果dis(src,a)+d(a,b)<dis(src,b),就把a设置为b的父节点
* 贪心:每一轮确定一个未访问节点中的距离原点最近的节点
* 在确定好的路径上,是原点到所有路径上点的最短路径
* 动态规划:自下而上,每次在原有的基础上,向后扩展
* */
#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
const int N=5;
const int src=0;
const int des=N-1;
int edge[N][N];
void init(){
//初始化邻接矩阵
memset(edge,-1,sizeof(edge));
edge[0][1]=10;
edge[0][2]=1;
edge[0][3]=3;
edge[2][1]=1;
edge[1][4]=20;
}
int main(){
init();
bool visit[N];
int parent[N];
int dist[N];
memset(visit,false,sizeof(visit));
memset(parent,-1,sizeof(parent));
memset(dist,0x3f,sizeof(dist));
int now=src;
visit[src]=true;
dist[src]=0;
int count=1; //已访问的节点数
while(count<N && !visit[des]){
count++;
//更新当前能到达的节点的dist信息
for(int i=0;i<N;i++){
if(!visit[i] && edge[now][i]!=-1 && dist[now]+edge[now][i]<dist[i]){
parent[i]=now;
dist[i]=dist[now]+edge[now][i];
}
}
//在未选顶点中,选出距离远点最近的顶点,确定它的最短路径
int minDist=0x3f3f3f3f;
for(int i=0;i<N;i++){
if(!visit[i])
{
if(dist[i]<minDist){
minDist=dist[i];
now=i;
}
}
}
visit[now]=true;
}
//给出最短路径
stack<int>path;
int t=des;
while(t!=-1){
path.push(t);
t=parent[t];
}
while(!path.empty()){
cout<<path.top()<<" ";
path.pop();
}
return 0;
}
/*
* 最短路路径:Dijkstra,floyd
* 最小生成树MST:Prim,Kruskal*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
const int MAX=1e9+7;
//图的表示,邻接矩阵、邻接表
int graph[100][100]; //存储无向图
int N; //节点个数
int M; //边个数
void init(){
fill(*graph,*graph+10000,MAX);
for(int i=0;i<100;i++)
graph[i][i]=0;
cin>>N>>M;
int src,des,d;
for(int i=0;i<M;i++){
cin>>src>>des>>d;
graph[src][des]=d;
graph[des][src]=d;
}
}
//最短路径:迪杰斯特拉算法,求解单源最短路径,算法复杂度O(N^2)
void dijkstra(){
vector<bool>visit(N,false);
vector<int>parent(N,-1);
vector<int>d_src(N,MAX); //初始为无限远
visit[0]=true;
d_src[0]=0;
int newNode=0;
int visitNum=1; //@todo 需要更新
while(visitNum<N){
//更新刚加入节点与**未访问顶点集**的距离信息
for(int i=0;i<N;i++){
if(newNode==i || visit[i] || graph[newNode][i]+d_src[newNode]>=d_src[i])
continue;
parent[i]=newNode;
d_src[i]=graph[newNode][i]+d_src[newNode];
}
//加入距离**起点**最近的点
int minNode=-1;
int min_d_src=MAX;
for(int i=0;i<N;i++){
if(visit[i])
continue;
if(d_src[i]<min_d_src){
min_d_src=d_src[i];
minNode=i;
}
}
visit[minNode]=true;
newNode=minNode;
visitNum++;
}
//找特定点的最短路径
int op;
cout<<"enter node index to show shortest path, enter -1 to exit:\n";
while(1){
cin>>op;
if(op==-1)
break;
stack<int>st;
st.push(op);
while(parent[st.top()]!=-1){
st.push(parent[st.top()]);
}
while(!st.empty()){
int t=st.top();
st.pop();
if(!st.empty()){
cout<<t<<"->";
}else
cout<<t;
}
cout<<endl;
}
}
//最短路径,kruskal算法,计算任意两点之间的最短路径
void floyd(){
vector<vector<int> >path(N,vector<int>(N,MAX));
vector<vector<int> >parent(N,vector<int>(N,-1)); //parent[i][j]表示i到j路径,从i下一步要到哪个节点,-1表示两个节点之间没有路径
//当parent[i][j]==j的时候,说明两个节点相邻
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(graph[i][j]!=MAX){
path[i][j]=graph[i][j];
parent[i][j]=j;
}
}
}
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
for(int k=0;k<N;k++){
int &ab=path[i][j];
int acb=path[i][k]+path[k][j];
if(acb<ab){
ab=acb;
parent[i][j]=parent[i][k];
}
}
}
}
//可以求出任意两点之间的最短路径
cout<<"enter two index to calculate shortest path,enter -1 to exit:\n";
int a,b;
while(1){
cin>>a;
if(a==-1)
break;
cin>>b;
if(path[a][b]==MAX){
cout<<"There is no path between them"<<endl;
continue;
}
cout<<path[a][b]<<endl;
int src=a;
while(src!=b){
cout<<src<<"->";
src=parent[src][b];
}
cout<<b<<endl;
}
}