PAT甲级 1030 Travel Plan
题目输入
line1 : N (城市个数) M(城市间边数) S(起点城市编号) D(终点城市编号)
line 2 ~ M +1 : City1(城市编号1) City2(城市编号2) Distance(城市间边第一权重)Cost(城市间边第二权重)
要求输出
line1 : 最短路径节点编号序列(从S—>D, 其中路径所含edge的Distance和Cost之和均要最小) 最短路径的Distance和 最短路径的Cost和
代码示例
文件“A 1030 Travel Plan.h”
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
#define MAX 510 //array capacity
#define INF 100000000 //infinity
//given
int num_cities, num_ways, id_start, id_des; //define variables for input in line1
int weightDist[MAX][MAX], weightCost[MAX][MAX]; //define 2 weighted graph
//assistance
bool IsVisited[MAX] = { false }; //check vertexs which are visited or not
#define NewOptPath(id_pre, id_ct) ( Dis_optPath[id_pre] + weightDist[id_pre][id_ct] < Dis_optPath[id_ct] ) //is there a smaller total distance
#define UpdateOptDist(id_pre, id_ct) ( Dis_optPath[id_ct] = Dis_optPath[id_pre] + weightDist[id_pre][id_ct] ) //update total distance
#define SameOptPath(id_pre, id_ct) ( Dis_optPath[id_pre] + weightDist[id_pre][id_ct] == Dis_optPath[id_ct] ) //is there a equal total distance but different path
//calculate
int Dis_optPath[MAX], Cos_optPath = INF; //optDistance of each city (from id_start) & Cost of optPath (from id_start to id_des)
vector<int> pre[MAX]; //closest predecessor of each city
vector<int> tempPath, optPath; //temporary path & opt path
void Dijkstra() {
//initial Distance & Cost of optPath
fill(Dis_optPath, Dis_optPath + MAX, INF);
Dis_optPath[id_start] = 0; //默认 id_start--->id_start 的total distance 为0
//n个顶点依次作为id_pre
for (int i = 0; i < num_cities; i++) {
int id_pre = -1, MIN = INF; //initialize, easy to find isolated city
for(int id_ct = 0; id_ct < num_cities; id_ct++) //find a vertex
//search for unVisited & min of Dis_optPath
if (!IsVisited[id_ct] && Dis_optPath[id_ct] < MIN) {
id_pre = id_ct;
MIN = Dis_optPath[id_ct];
}
if (id_pre == -1) return; //cannot find
//find
IsVisited[id_pre] = true; //mark
for (int id_ct = 0; id_ct < num_cities; id_ct++) { //遍历n个顶点,check 以id_pre为pred时是否要优化
if (!IsVisited[id_ct] && weightDist[id_pre][id_ct] < INF) { //unvisited & reachable vertex
if (NewOptPath(id_pre, id_ct)) {
UpdateOptDist(id_pre, id_ct);
pre[id_ct].clear(); //clear predecessor of id_ct
pre[id_ct].push_back(id_pre); //update closest predecesspr
}
else if( SameOptPath(id_pre, id_ct) )
pre[id_ct].push_back(id_pre); //update predecesspr directly
}
}
}
}
void DFS( int id_ct ) {
//iteration base
if (id_ct == id_start) {
tempPath.push_back(id_ct); //add id_ct in tempPath
//calculate tempCost of tempPath
int tempCost = 0; //initialize
for (int i = tempPath.size() - 1; i > 0; i--) { //add cost from back to forth
int idV = tempPath[i], idVNext = tempPath[i - 1];
tempCost += weightCost[idVNext][idV];
}
//is there a smaller optCost
if (tempCost < Cos_optPath) {
Cos_optPath = tempCost; //update Cos_optPath
optPath = tempPath; //update optPath
}
tempPath.pop_back(); //tempPath的首节点出栈
return;
}
tempPath.push_back(id_ct); //入栈
for( unsigned i = 0; i < pre[id_ct].size(); i++) //每个前驱遍历其所有optPath
DFS( pre[id_ct][i] ); //顺序选一条optPath深入,直到遇到leaf
tempPath.pop_back(); //每check完一个tempPath上一个节点, 节点出栈
}
文件“main.cpp”
int main() {
//input line1
scanf("%d %d %d %d", &num_cities, &num_ways, &id_start, &id_des);
//input line2~M+1 matrix
//initialize
fill(weightDist[0], weightDist[0]+ MAX * MAX, INF); //weightDist[][] = INF
fill(weightCost[0], weightCost[0] + MAX * MAX, INF); //weightCost[][] = INF
for (int i = 0; i < num_cities; i++) //self-reachable
weightDist[i][i] = 0, weightCost[i][i] = 0;
//input
int id_ct1 = 0, id_ct2 = 0;
for (int i = 0; i < num_ways; i++) {
scanf("%d %d", &id_ct1, &id_ct2);
scanf("%d", &weightDist[id_ct1][id_ct2]);
scanf("%d", &weightCost[id_ct1][id_ct2]);
weightDist[id_ct2][id_ct1] = weightDist[id_ct1][id_ct2]; //directed weightDist graph
weightCost[id_ct2][id_ct1] = weightCost[id_ct1][id_ct2]; //directed weightCost graph
}
//调用算法
Dijkstra(); //1.记录最短路径每层的最优前驱集合(有多少条Dist_optPath可以到达该层)
DFS( id_des ); //calculate Cost_optPath based on Dist_optPath
//output
//line1: cities from id_start--->id_des
for (int i = optPath.size() - 1; i >= 0; i--) //从栈顶开始输出
//optPath.size() == 0 ???d
printf("%d ", optPath[i]); //不要加“&”!!!
//line2: distance & cost
printf("%d %d\n", Dis_optPath[id_des], Cos_optPath); //不要加“&”
return 0;
}