1030. Travel Plan 解析

直接Dijstra感觉简单点,这个第二标尺比较容易想明白。Dijstra+DFS感觉反而麻烦了一点 两个都写了下练练手。


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <climits>
#include <stack>

#define MAX 510

using namespace std;


struct Node {
	int v;
	int dis;
	int cost;
};

vector <Node> g[MAX];

vector <bool> isVis;
vector <int> pre[MAX];
vector <int> dis;
vector <int> cost;
int P[MAX];
int C[MAX];


int N, M, S, D;

void dijstra(int st) { //st 起点
	
	dis[st] = 0;
	C[st] = 0;

	for (int i = 0; i < N; i++) {
		
		int min = INT_MAX, u = -1;

		for (int j = 0;j < N; j++) { //找最小距离
			if (!isVis[j] && min > dis[j]) {
				min = dis[j];
				u = j;
			}
		}

		if (u == -1) return;//没有最小值

		isVis[u] = true;

		for (int j = 0; j < g[u].size(); j++) {
			int v = g[u][j].v;
			if (!isVis[v]) {
				if (dis[v] > dis[u] + g[u][j].dis) {
					dis[v] = dis[u] + g[u][j].dis;
					pre[v].clear();
					pre[v].push_back(u);
					//法二
					P[v] = u;
					C[v] = C[u] + g[u][j].cost;
				}
				else if (dis[v] == dis[u] + g[u][j].dis) {
					pre[v].push_back(u);
					//法二
					if (C[v] > C[u] + g[u][j].cost) {
						P[v] = u;
						C[v] = C[u] + g[u][j].cost;
					}
				}
			}
		}
	}
}

vector <int> patch, ThisPath;
int MinCost = INT_MAX;

void DFS(int v) {
	if (v == S) { //到达起点
		ThisPath.push_back(v);
		int ThisCost = 0;
		int ID = 0;
		int IDN = 0;
		for (int i = ThisPath.size() - 1; i > 0; i--) {
			ID = ThisPath[i];
			IDN = ThisPath[i - 1];
			for (int j = 0; j < g[ID].size(); j++) {
				if (g[ID][j].v == IDN)
					IDN = j;
			}
			ThisCost += g[ID][IDN].cost;
		}
		if (ThisCost < MinCost) {
			MinCost = ThisCost;
			patch = ThisPath;
		}
		ThisPath.pop_back();
		return;
	}
	ThisPath.push_back(v);
	for (int i = 0; i < pre[v].size(); i++) {
		DFS(pre[v][i]);
	}
	ThisPath.pop_back();
	
}


int main() {
	cin >> N >> M >> S >> D;

	isVis.resize(N, false);
	dis.resize(N,INT_MAX);
	cost.resize(N, INT_MAX);
	
	for (int i = 0; i < N; i++) {
		C[i] = INT_MAX;
		P[i] = -1;
	}

	int Head, Tail;
	Node temp;
	for (int i = 0; i < M; i++) {
		cin >> Head >> Tail >> temp.dis >> temp.cost;
		temp.v = Tail;
		g[Head].push_back(temp);
		temp.v = Head;
		g[Tail].push_back(temp);
	}

#ifdef _DEBUG
	for (int i = 0; i < N; i++) {	
		for (int j = 0; j < g[i].size(); j++) {
		 	cout <<i << " " <<  g[i][j].v << " dis:" << g[i][j].dis << " cost:" << g[i][j].cost << endl;
		}
	}
#endif


	//法一
	dijstra(S);
	DFS(D);

	for (int i = patch.size() - 1; i >= 0; i--) {
		cout << patch[i] << " ";
	}
	cout << dis[D] << " " << MinCost << endl;


#ifdef _DEBUG
	for (int i = 0; i < N; i++) {
		cout << "-------" << i << "--------" << endl;
		for (int j = 0; j < pre[i].size(); j++) {
			cout << pre[i][j] << endl;
		}
	}
#endif
		




	//法二
	//stack <int> s;
	//int p = D;
	//while (p != -1) {
	//	s.push(p);
	//	p = P[p];
	//}
	//while (!s.empty()) {
	//	cout << s.top() << " ";
	//	s.pop();
	//}
	//cout << dis[D] << " " << C[D] << endl;




	system("pause");

	return 0;


}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值