每日算法:Dijkstra+DFS

日期:2023.10.18

第8天

题目来源:patA1030

代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
int n, m, s, d;
const int INF = 0x3f3f3f3f;
const int MAXN = 510;
int G[MAXN][MAXN];
int dijk[MAXN];
int vis[MAXN] = {0};
int cost[MAXN][MAXN];//路上的消耗 
vector<int> pre[MAXN];
int totalDis = 0 , totalCost = INF;
vector<int> path, tempPath;

//找出每个点的最短路径 
void Dijkstra(int s) {
	memset(dijk, 0x3f, sizeof(dijk));
	dijk[s] = 0;
	
	for(int i = 0; i < n; i++) {
		int u = -1, MIN = INF;
		//找到非集合S中距离起点最近的点 
		for(int j = 0; j < n; j++) {
			if(vis[j] == 0 && dijk[j] < MIN) {
				u = j;
				MIN = dijk[j];
			}
		}
		if(u == -1) return ;
		//将找出来的点加入集合S 
		vis[u] = 1; //这一步容易忘记 
		
		
		//更新非集合S中的长度,记录路径
		for(int v = 0; v < n; v++) {
			if(G[u][v] != INF && vis[v] == 0) {
				if(dijk[u] + G[u][v] < dijk[v]) {
					dijk[v] = dijk[u] + G[u][v];
					pre[v].clear();
					pre[v].push_back(u);
				}
				else if(dijk[u] + G[u][v] == dijk[v]) {
					pre[v].push_back(u);
				}
			}
		} 
		
		
	} 
	
}

//找出最短路径中,第二标尺最优的
void DFS(int v) {
	if(v == s) {
		tempPath.push_back(v);
		//计算当前路径上的花费
		int tempCost = 0;
		for(int i = tempPath.size() - 1; i > 0; i--) {
			int id = tempPath[i], idNext = tempPath[i-1];
			tempCost += cost[id][idNext];
		}
		if(tempCost < totalCost) {
			totalCost = tempCost;
			path = tempPath;
		}
		tempPath.pop_back();
		return ;
	}
	tempPath.push_back(v);
	for(int i = 0; i < pre[v].size(); i++) {
		DFS(pre[v][i]);
	}
	tempPath.pop_back();
} 

int main(void) {
	scanf("%d%d%d%d", &n, &m, &s, &d);
	
	//边进行初始化
	memset(G, 0x3f, sizeof(G)); 
	for(int i = 0; i < m; i++) {
		int v1, v2, dis, c;
		scanf("%d%d%d%d", &v1, &v2, &dis, &c);
		G[v1][v2] = G[v2][v1] = dis;
		cost[v1][v2] = cost[v2][v1] = c;
	}
	Dijkstra(s);
	DFS(d);
	
	
	
	for(int i = path.size() - 1; i >= 0; i--) {
		printf("%d ", path[i]);
	}
	
	printf("%d %d", dijk[d], totalCost);
	
	
	return 0;
}

问题:

        1.牢记Dijkstra算法的三步骤;

                a.将非集合S中距离起点最近的找出来;

                b.将该点加入到集合S;

                c.更新非集合S中的点到起点的距离;

        第二步容易忘记,vis[v] = 1;

        2.其实Dijkstra+DFS对复杂题更有用,如果只有一个第二标尺,完全可以直接用Dijkstra处理,这样更方便更快;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前路漫漫亦灿灿上岸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值