最短路问题

一:单源最短路

1:Bellman-Ford算法

/**
单源最短路问题(Bellman-Ford算法) 
输入
5 6
0 1 2
1 2 1
2 3 4
3 4 3
0 4 5
0 3 2
输出
3
**/ 
#include<stdio.h>
#include<iostream>
#define INF 9999999
using namespace std;
struct edge{
	int from,to,cost;
};
edge es[100]; //边
int  d[100]; //最短距离
int V,E;  //V是顶点数,E是边数

//求解从节点S出发到所有点的最短距离
void shortest_path(int s){
	for(int i=0;i<V;i++){
		d[i]=INF;
	}
	d[s]=0;
	while(true){
		bool update =false;
		
		//寻找起点不是INF,而且终点到源点权值大于起点到源点权值加上边权值的边 
		for(int i=0;i<E;i++){
			edge e=es[i];
			if(d[e.from]!=INF&&d[e.to]>d[e.from]+e.cost){
				d[e.to]=d[e.from]+e.cost;
				update=true;
			}
		}
		if(!update){
			break;
		}
	}
} 
int main(){
	int from,to,cost; 
	scanf("%d%d",&V,&E);
	//边数为E但需要2*E个存储无向图 
	E=E*2;
	for(int i=0;i<E;i=i+2){
		scanf("%d%d%d",&from,&to,&cost);
		es[i].from=from;
		es[i].to=to;
		es[i].cost=cost;
		es[i+1].from=to;
		es[i+1].to=from; 
		es[i+1].cost=cost;
	}
	//假如从2点出发,求到0点最短距离 
	shortest_path(2);
	printf("%d",d[0]);
	return 0;
} 

2:dijkstra算法

/**
单源最短路问题(dijkstra算法) 
输入
5 6
0 1 2
1 2 1
2 3 4
3 4 3
0 4 5
0 3 2
输出
3
**/
#include<stdio.h>
#include<algorithm> 
#include<cstring>
#define INF 999999
using namespace std;
int cost[100][100]; //cost[u][v]表示边u,v的权值,不存在时设为INF 
int d[100];//顶点S出发的最短距离
bool used[100]; //已经使用过的图
int V,E; //定点数

//求从起点s出发的最短距离
void dijkstra(int s){
	fill(d,d+V,INF);
	fill(used,used+V,false);
	d[s]=0;
	while(true){
		int v=-1;
		//从未使用过的顶点中选择一个距离最小的顶点
		for(int u=0;u<V;u++){
			if(!used[u]&&(v==-1||d[u]<d[v])){
				v=u;
			}
		} 
		if(v==-1){
			break;
		} 
		used[v]=true;
		for(int u=0;u<V;u++){
			d[u]=min(d[u],d[v]+cost[v][u]);
		}
	}
}
int main(){
	int tempx,tempy,co;
	scanf("%d%d",&V,&E);
	//边权初始化为INF
	for(int i=0;i<V;i++)
	for(int j=0;j<V;j++){
		cost[i][j]=INF;
	}
	for(int i=0;i<E;i++){
		scanf("%d%d%d",&tempx,&tempy,&co);
		cost[tempx][tempy]=co;
		cost[tempy][tempx]=co;
	}
	//假如从2点出发,求到0点最短距离 
	dijkstra(2);
	printf("%d\n",d[0]);
	return 0;
}

3:dijkstra算法优化

/**
单源最短路问题(dijkstra算法优化) 
输入
5 6
0 1 2
1 2 1
2 3 4
3 4 3
0 4 5
0 3 2
输出
3
**/
#include<stdio.h>
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
#define INF 9999999 
using namespace std;
typedef pair<int ,int> P; //first是最短距离,second是顶点 
struct edge{
	int to,cost;
}; 
int V,E;//V是顶点数,E是边数
vector<edge> G[100];
int d[100];
void dijkstra(int s){
	//通过greater<p>参数,堆按照从大到小的顺序取出值
	priority_queue<P,vector<P>,greater<P> >que;
	fill(d,d+V,INF);
	d[s]=0;
	que.push(P(0,s));
	while(!que.empty()){
		P p=que.top();
		que.pop();
		int v=p.second;
		if(d[v]<p.first){
			continue;
		}
		for(int i=0;i<G[v].size();i++){
			edge e=G[v][i];
			if(d[e.to]>d[v]+e.cost){
				d[e.to]=d[v]+e.cost;
				que.push(P(d[e.to],e.to));
			}
		}
	}
} 
int main(){
	int from,to,cost; 
	scanf("%d%d",&V,&E);
	for(int i=0;i<E;i++){
		edge tempe1,tempe2;
		scanf("%d%d%d",&from,&to,&cost);
		tempe1.to=to;
		tempe1.cost=cost;
		G[from].push_back(tempe1);
		tempe2.to=from;
		tempe2.cost=cost;
		G[to].push_back(tempe2);
	}
	//假如从2点出发,求到0点最短距离 
	dijkstra(2);
	printf("%d\n",d[0]);
	return 0;
}

二:多源最短路

/**
多源最短路问题(Floyd-Warshall算法) 
输入
5 6
0 1 2
1 2 1
2 3 4
3 4 3
0 4 5
0 3 2
输出
3
**/
#include<stdio.h>
#include<iostream>
#include<algorithm>
#define INF 9999999
using namespace std;
int d[100][100];  //d[u][v]表示边uv的权值 (不存在时设为INF,但是d[i][i]为0)
int V,E;  //V顶点数,E边数 
void warshall_floyd(){
	for(int k=0;k<V;k++){
		for(int i=0;i<V;i++){
			for(int j=0;j<V;j++){
				d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
			}
		}
	}
}
int main(){	
	scanf("%d%d",&V,&E);
	for(int i=0;i<V;i++)
	for(int j=0;j<V;j++){
		if(i==j){
			d[i][j]=0;
		}else{
			d[i][j]=INF;
		}
	}
	for(int i=0;i<E;i++){
		int tempx,tempy,tempco;
		scanf("%d%d%d",&tempx,&tempy,&tempco);
		d[tempx][tempy]=tempco;
		d[tempy][tempx]=tempco;
	} 
	warshall_floyd(); 
	//假如从2点出发,求到0点最短距离 
	printf("%d\n",d[2][0]);
	return 0;
}

三:路径还原

用prev数组记录最短路径前驱节点

/**
还原路径问题(dijkstra算法) 
输入
5 6
0 1 2
1 2 1
2 3 4
3 4 3
0 4 5
0 3 2
输出
3
**/
#include<stdio.h>
#include<algorithm> 
#include<vector>
#define INF 999999
using namespace std;
int cost[100][100]; //cost[u][v]表示边u,v的权值,不存在时设为INF 
int d[100];//顶点S出发的最短距离
bool used[100]; //已经使用过的图
int V,E; //定点数
int prev[100];  //最短路的前驱节点 

//求从起点s出发的最短距离
void dijkstra(int s){
	fill(d,d+V,INF);
	fill(used,used+V,false);
	fill(prev,prev+V,-1); 
	d[s]=0;
	while(true){
		int v=-1;
		//从未使用过的顶点中选择一个距离最小的顶点
		for(int u=0;u<V;u++){
			if(!used[u]&&(v==-1||d[u]<d[v])){
				v=u;
			}
		} 
		if(v==-1){
			break;
		} 
		used[v]=true;
		for(int u=0;u<V;u++){
			if(d[u]>d[v]+cost[v][u]){
				d[u]=d[v]+cost[v][u];
				prev[u]=v;
			}	
		}
	}
}
//到顶点t的最短路
vector<int> get_path(int t){
	vector<int> path;
	for(;t!=-1;t=prev[t]){
		path.push_back(t);//不断沿着prev[t]走直到t=s
	}
	//这样得到的t-s,所以反转
	reverse(path.begin(),path.end());
	return path; 
} 
int main(){
	int tempx,tempy,co;
	scanf("%d%d",&V,&E);
	//边权初始化为INF
	for(int i=0;i<V;i++)
	for(int j=0;j<V;j++){
		cost[i][j]=INF;
	}
	for(int i=0;i<E;i++){
		scanf("%d%d%d",&tempx,&tempy,&co);
		cost[tempx][tempy]=co;
		cost[tempy][tempx]=co;
	}
	//假如从2点出发,求到0点最短距离和路径 
	dijkstra(2);
	printf("%d\n",d[0]); 
	vector<int> path=get_path(0);
	for(int i=0;i<path.size();i++){
		printf("%d ",path[i]);
	} 
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值