最短路记录路径(Dijkstra&Floyd)

窝这里Dijkstra是用的优先队列优化版的,适用于那些个卡时间卡空间的题目,用前向星存的图,老师上课讲的二维数组版的也没怎么听(QAQ)后面有空再补吧~

先贴代码:

Floyd (先来简单的)

#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
int t,n,m,dis[100][100];
string p[10][10];
string ch[]={"","A","B","C","D","E"};
void path(int x,int y,int z){
	int sz=p[x][y].size();
	string tp="";
	for(int i=0;i<sz-1;i++)tp=tp+p[x][y][i];//拼接时去掉前部分最后一个字母避免重复 
	p[x][z]=tp+p[y][z]; 
}
int main(){
	//ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j){
				dis[i][j]=0;
				p[i][j]="";
			}
			else{
				dis[i][j]=inf;
				p[i][j]=ch[i]+ch[j];
			}
		}
	}
	for(int i=0,u,v,w;i<m;i++){
		cin>>u>>v>>w;
		dis[u][v]=dis[v][u]=w;
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(k!=i&&k!=j&&i!=j)
					if(dis[i][j]>dis[i][k]+dis[k][j]){
						dis[i][j]=dis[i][k]+dis[k][j];
						path(i,k,j);//记录路径 
					}
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			printf("%4d",dis[i][j]);
		cout<<'\n';
	}
	cout<<'\n'; 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			cout<<p[i][j]<<"	";
		cout<<'\n';
	}
	return 0;
}

/*
5 7
1 2 10
2 3 50
1 4 30
1 5 100
3 5 10
3 4 20
4 5 60
*/

 运行截图:

 Dijkstra:

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N=1e4+5,M=2e5+5;
int ct,n,m,s,t,dis[N],head[N],vis[N];
int ans[N],las[N];//用于记录路径 
struct edge{
	int t,l,next;
}e[M];
struct ty{
	int x,dis;
	bool operator < (const ty & a)const{
		return dis>a.dis;
	}
};
priority_queue<ty> q;
void addedge(int u,int v,int w){//前向星存边 
	e[++ct].t=v;
	e[ct].l=w;
	e[ct].next=head[u];
	head[u]=ct;
}
int Dij(int s,int t){
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0;
	ty tmp;
	tmp.x=s, tmp.dis=0;
	q.push(tmp);
	while(!q.empty()){
		tmp=q.top();
		q.pop();
		if(vis[tmp.x])continue;
		vis[tmp.x]=1;
		for(int i=head[tmp.x];~i;i=e[i].next){
			int y=e[i].t;
			if(dis[y]>dis[tmp.x]+e[i].l){
				dis[y]=dis[tmp.x]+e[i].l;
				ty tmp2;
				tmp2.x=e[i].t, tmp2.dis=dis[y];
				q.push(tmp2);
				las[y]=tmp.x;//更新时记录上一个点 
			}
		}
	}
	return dis[t];
}
int main(){
	cin>>n>>m>>s>>t;//n:点个数,m:边数,s:起始点,t:终点 
	memset(head,-1,sizeof(head));
	int x,y,z;
	for(int i=0;i<m;i++){
		cin>>x>>y>>z;
		addedge(x,y,z);
		addedge(y,x,z);
	}
	cout<<Dij(s,t)<<'\n';
	ct=0;
	int pos=t;
	while(pos!=s){
		ans[++ct]=pos,pos=las[pos];
	}
	cout<<s<<' ';
	for(int i=ct;i>=1;i--)cout<<ans[i]<<' ';
	return 0;
}
/*测试数据: 
5 7 1 5
1 2 10
2 3 50
1 4 30
1 5 100
3 5 10
3 4 20
4 5 60
*/

运行截图:

 太懒了

贴完跑路

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值