1087 条条大路通罗马

``````6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1``````

``````3 3 195 97
HZH->PRS->ROM``````

### 思路一：Dijkstra算法+深度优先遍历（邻接表实现）

C++代码：

``````#include<iostream>
#include<vector>
#include<map>
#include<string>

using namespace std;

struct node {
int v;	//节点编号
int cost;	//边权值
node(int _v, int _cost) : v(_v), cost(_cost) {}	//构造函数
};

int N;	//城市数量
int K;	//道路条数
int INF = 1000000000;	//无穷大数
string start;	//起始点城市名字
int happy[201];	//存放各个城市的快乐值
map<string, int> stringToInt;	//城市名字->编号
map<int, string> intToString; 	//编号->城市名字
vector<node> graph[201];	//无向图
int d[201];	//记录从起始城市到达点i的最少花费值
bool visited[201];	//标记数组
vector<int> pre[201];	//记录前一个节点
vector<int> path;
vector<int> tempPath;
int optHappy = 0;
double optAverageHappy = 0.0;
int count = 0;	//记录最短路径条数

void dijkstra(int s);
void dfs(int nowVisit);

int main() {
cin >> N >> K >> start;
stringToInt[start] = 0;	//起始城市编号为0
intToString[0] = start;
string city;
int happyness;
for(int i = 1; i <= N - 1; i++) {
cin >> city >> happyness;
stringToInt[city] = i;
intToString[i] = city;
happy[i] = happyness;
}
string city1, city2;
int cost;
for(int i = 0; i < K; i++) {
cin >> city1 >> city2 >> cost;
int id1 = stringToInt[city1];
int id2 = stringToInt[city2];
graph[id1].push_back(node(id2, cost));
graph[id2].push_back(node(id1, cost));
}
int destination = stringToInt["ROM"];
dijkstra(0);
dfs(destination);
cout << count << " " << d[destination] << " " << optHappy << " " << (int)optAverageHappy << endl;
for(int i = path.size() - 1; i >= 0; i--){
cout << intToString[path[i]];
if(i != 0){
cout << "->";
}
}
return 0;
}

void dijkstra(int s){
for(int i = 0; i < N; i++){
d[i] = INF;
}
d[s] = 0;
for(int i = 0; i < N; i++){
int u = -1, min = INF;
for(int j = 0; j < N; j++){
if(!visited[j] && d[j] < min){
min = d[j];
u = j;
}
}
if(u == -1){
return;
}
visited[u] = true;
for(int j = 0; j < graph[u].size(); j++){
int v = graph[u][j].v;
int cost = graph[u][j].cost;
if(!visited[v]){
if(d[u] + cost < d[v]){
d[v] = d[u] + cost;
pre[v].clear();
pre[v].push_back(u);
}else if(d[u] + cost == d[v]){
pre[v].push_back(u);
}
}
}
}
}

void dfs(int nowVisit){
if(nowVisit == 0){
count++;
tempPath.push_back(nowVisit);
int happyValue = 0;
for(int i = tempPath.size() - 2; i >= 0; i--){
happyValue += happy[tempPath[i]];
}
double averageHappyValue = 1.0 * happyValue / (tempPath.size() - 1);
if(happyValue > optHappy){
optHappy = happyValue;
optAverageHappy = averageHappyValue;	//也需要更新optAverageHappy的值
path = tempPath;
}else if(happyValue == optHappy && averageHappyValue > optAverageHappy){
optAverageHappy = averageHappyValue;
path = tempPath;
}
tempPath.pop_back();
return;
}
tempPath.push_back(nowVisit);
for(int i = 0; i < pre[nowVisit].size(); i++){
dfs(pre[nowVisit][i]);
}
tempPath.pop_back();
} ``````

C++解题报告：

### 思路二：Bellman-Ford算法+深度优先遍历（邻接表实现）

C++代码：

``````#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<set>

using namespace std;

struct node {
int v;	//节点编号
int cost;	//边权值
node(int _v, int _cost) : v(_v), cost(_cost) {}	//构造函数
};

int N;	//城市数量
int K;	//道路条数
int INF = 1000000000;	//无穷大数
string start;	//起始点城市名字
int happy[201];	//存放各个城市的快乐值
map<string, int> stringToInt;	//城市名字->编号
map<int, string> intToString; 	//编号->城市名字
vector<node> graph[201];	//无向图
int d[201];	//记录从起始城市到达点i的最少花费值
set<int> pre[201];	//记录前一个节点
vector<int> path;
vector<int> tempPath;
int optHappy = 0;
double optAverageHappy = 0.0;
int count = 0;	//记录最短路径条数

bool bellmanFord(int s);
void dfs(int nowVisit);

int main() {
cin >> N >> K >> start;
stringToInt[start] = 0;	//起始城市编号为0
intToString[0] = start;
string city;
int happyness;
for(int i = 1; i <= N - 1; i++) {
cin >> city >> happyness;
stringToInt[city] = i;
intToString[i] = city;
happy[i] = happyness;
}
string city1, city2;
int cost;
for(int i = 0; i < K; i++) {
cin >> city1 >> city2 >> cost;
int id1 = stringToInt[city1];
int id2 = stringToInt[city2];
graph[id1].push_back(node(id2, cost));
graph[id2].push_back(node(id1, cost));
}
int destination = stringToInt["ROM"];
bellmanFord(0);
dfs(destination);
cout << count << " " << d[destination] << " " << optHappy << " " << (int)optAverageHappy << endl;
for(int i = path.size() - 1; i >= 0; i--) {
cout << intToString[path[i]];
if(i != 0) {
cout << "->";
}
}
return 0;
}

bool bellmanFord(int s) {
for(int i = 0; i < N; i++) {
d[i] = INF;
}
d[s] = 0;
for(int i = 0; i < N - 1; i++) {
for(int u = 0; u < N; u++) {
for(int j = 0; j < graph[u].size(); j++) {
int v = graph[u][j].v;
int cost = graph[u][j].cost;
if(cost + d[u] < d[v]) {
d[v] = cost + d[u];
pre[v].clear();
pre[v].insert(u);
} else if(cost + d[u] == d[v]) {
pre[v].insert(u);
}
}
}
}
for(int u = 0; u < N; u++) {
for(int j = 0; j < graph[u].size(); j++) {
int v = graph[u][j].v;
int cost = graph[u][j].cost;
if(cost + d[u] < d[v]) {
return false;
}
}
}
return true;
}

void dfs(int nowVisit) {
if(nowVisit == 0) {
count++;
tempPath.push_back(nowVisit);
int happyValue = 0;
for(int i = tempPath.size() - 2; i >= 0; i--) {
happyValue += happy[tempPath[i]];
}
double averageHappyValue = 1.0 * happyValue / (tempPath.size() - 1);
if(happyValue > optHappy) {
optHappy = happyValue;
optAverageHappy = averageHappyValue;
path = tempPath;
} else if(happyValue == optHappy && averageHappyValue > optAverageHappy) {
optAverageHappy = averageHappyValue;
path = tempPath;
}
tempPath.pop_back();
return;
}
tempPath.push_back(nowVisit);
set<int>::iterator it;
for(it = pre[nowVisit].begin(); it != pre[nowVisit].end(); it++){
dfs(*it);
}
tempPath.pop_back();
}``````

C++解题报告：

### 思路三：SPFA算法+深度优先遍历（邻接表实现）

C++代码：

``````#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<set>
#include<queue>

using namespace std;

struct node {
int v;	//节点编号
int cost;	//边权值
node(int _v, int _cost) : v(_v), cost(_cost) {}	//构造函数
};

int N;	//城市数量
int K;	//道路条数
int INF = 1000000000;	//无穷大数
string start;	//起始点城市名字
int happy[201];	//存放各个城市的快乐值
map<string, int> stringToInt;	//城市名字->编号
map<int, string> intToString; 	//编号->城市名字
vector<node> graph[201];	//无向图
int d[201];	//记录从起始城市到达点i的最少花费值
set<int> pre[201];	//记录前一个节点
vector<int> path;
vector<int> tempPath;
int optHappy = 0;
double optAverageHappy = 0.0;
int count = 0;	//记录最短路径条数
bool inq[201] = {false};	//记录节点是否在队列中
int countInq[201] = {0};	//统计每个节点的入队次数

bool spfa(int s);
void dfs(int nowVisit);

int main() {
cin >> N >> K >> start;
stringToInt[start] = 0;	//起始城市编号为0
intToString[0] = start;
string city;
int happyness;
for(int i = 1; i <= N - 1; i++) {
cin >> city >> happyness;
stringToInt[city] = i;
intToString[i] = city;
happy[i] = happyness;
}
string city1, city2;
int cost;
for(int i = 0; i < K; i++) {
cin >> city1 >> city2 >> cost;
int id1 = stringToInt[city1];
int id2 = stringToInt[city2];
graph[id1].push_back(node(id2, cost));
graph[id2].push_back(node(id1, cost));
}
int destination = stringToInt["ROM"];
spfa(0);
dfs(destination);
cout << count << " " << d[destination] << " " << optHappy << " " << (int)optAverageHappy << endl;
for(int i = path.size() - 1; i >= 0; i--) {
cout << intToString[path[i]];
if(i != 0) {
cout << "->";
}
}
return 0;
}

bool spfa(int s) {
for(int i = 0; i < N; i++){
d[i] = INF;
}
d[s] = 0;
queue<int> q;
q.push(s);
inq[s] = true;
countInq[s]++;
while(!q.empty()){
int u = q.front();
q.pop();
inq[u] = false;
for(int j = 0; j < graph[u].size(); j++){
int v = graph[u][j].v;
int cost = graph[u][j].cost;
if(d[u] + cost < d[v]){
d[v] = d[u] + cost;
pre[v].clear();
pre[v].insert(u);
if(!inq[v]){
q.push(v);
inq[v] = true;
countInq[v]++;
if(countInq[v] > N){
return false;
}
}
}else if(d[u] + cost == d[v]){
pre[v].insert(u);
if(!inq[v]){
q.push(v);
inq[v] = true;
countInq[v]++;
if(countInq[v] > N){
return false;
}
}
}
}
}
return true;
}

void dfs(int nowVisit) {
if(nowVisit == 0) {
count++;
tempPath.push_back(nowVisit);
int happyValue = 0;
for(int i = tempPath.size() - 2; i >= 0; i--) {
happyValue += happy[tempPath[i]];
}
double averageHappyValue = 1.0 * happyValue / (tempPath.size() - 1);
if(happyValue > optHappy) {
optHappy = happyValue;
optAverageHappy = averageHappyValue;
path = tempPath;
} else if(happyValue == optHappy && averageHappyValue > optAverageHappy) {
optAverageHappy = averageHappyValue;
path = tempPath;
}
tempPath.pop_back();
return;
}
tempPath.push_back(nowVisit);
set<int>::iterator it;
for(it = pre[nowVisit].begin(); it != pre[nowVisit].end(); it++){
dfs(*it);
}
tempPath.pop_back();
}``````

C++解题报告：

### 思路四：Dijkstra算法+深度优先遍历（邻接矩阵实现）

C++代码：

``````#include<iostream>
#include<map>
#include<vector>
#include<string>

using namespace std;

int N;	//城市数量
int K;	//道路条数
int INF = 1000000000;
string start;	//起始城市
int graph[201][201];
map<string, int> stringToInt;	//城市名称->城市编号
map<int, string> intToString;	//城市编号->城市名称
int happy[201];	//每个城市的快乐数
int d[201];
bool visited[201] = {false};
vector<int> pre[201];
vector<int> tempPath;
vector<int> path;
int optValue1 = 0;
double optValue2 = 0;
int count = 0;

void dijkstra(int s);
void dfs(int nowVisit);

int main(){
cin >> N >> K >> start;
stringToInt[start] = 0;	//起始城市编号为0
intToString[0] = start;
string city;
int happyness;
for(int i = 1; i < N; i++){
cin >> city >> happyness;
stringToInt[city] = i;
intToString[i] = city;
happy[i] = happyness;
}
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
graph[i][j] = graph[j][i] = INF;
}
}
string city1, city2;
int cost;
for(int i = 0; i < K; i++){
cin >> city1 >> city2 >> cost;
int id1 = stringToInt[city1];
int id2 = stringToInt[city2];
graph[id1][id2] = graph[id2][id1] = cost;
}
dijkstra(0);
int destination = stringToInt["ROM"];
dfs(destination);
cout << count << " " << d[destination] << " " << optValue1 << " " << (int)optValue2 << endl;
for(int i = path.size() - 1; i >= 0; i--){
cout << intToString[path[i]];
if(i != 0){
cout << "->";
}
}
cout << endl;
return 0;
}

void dijkstra(int s){
for(int i = 0; i < N; i++){
d[i] = INF;
}
d[s] = 0;
for(int i = 0; i < N; i++){
int u = -1, min = INF;
for(int j = 0; j < N; j++){
if(!visited[j] && d[j] < min){
min = d[j];
u = j;
}
}
if(u == -1){
return;
}
visited[u] = true;
for(int v = 0; v < N; v++){
if(!visited[v] && graph[u][v] != INF){
if(d[u] + graph[u][v] < d[v]){
d[v] = d[u] + graph[u][v];
pre[v].clear();
pre[v].push_back(u);
}else if(d[u] + graph[u][v] == d[v]){
pre[v].push_back(u);
}
}
}
}
}

void dfs(int nowVisit){
tempPath.push_back(nowVisit);
if(nowVisit == 0){
count++;
int value1 = 0;
for(int i = tempPath.size() - 2; i >= 0; i--){
value1 += happy[tempPath[i]];
}
double value2 = value1 * 1.0 / (tempPath.size() - 1);
if(value1 > optValue1){
optValue1 = value1;
optValue2 = value2;
path = tempPath;
}else if(value1 == optValue1 && value2 > optValue2){
optValue2 = value2;
path = tempPath;
}
tempPath.pop_back();
return;
}
for(int i = 0; i < pre[nowVisit].size(); i++){
dfs(pre[nowVisit][i]);
}
tempPath.pop_back();
}``````

C++解题报告：

### 思路五：Bellman-Ford算法+深度优先遍历（邻接矩阵实现）

C++代码：

``````#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<set>

using namespace std;

int N;	//城市数量
int K;	//道路条数
int INF = 1000000000;
string start;	//起始城市
int graph[201][201];
map<string, int> stringToInt;	//城市名称->城市编号
map<int, string> intToString;	//城市编号->城市名称
int happy[201];	//每个城市的快乐数
int d[201];
set<int> pre[201];
vector<int> tempPath;
vector<int> path;
int optValue1 = 0;
double optValue2 = 0;
int count = 0;

bool bellmanFord(int s);
void dfs(int nowVisit);

int main() {
cin >> N >> K >> start;
stringToInt[start] = 0;	//起始城市编号为0
intToString[0] = start;
string city;
int happyness;
for(int i = 1; i < N; i++) {
cin >> city >> happyness;
stringToInt[city] = i;
intToString[i] = city;
happy[i] = happyness;
}
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
graph[i][j] = graph[j][i] = INF;
}
}
string city1, city2;
int cost;
for(int i = 0; i < K; i++) {
cin >> city1 >> city2 >> cost;
int id1 = stringToInt[city1];
int id2 = stringToInt[city2];
graph[id1][id2] = graph[id2][id1] = cost;
}
bellmanFord(0);
int destination = stringToInt["ROM"];
dfs(destination);
cout << count << " " << d[destination] << " " << optValue1 << " " << (int)optValue2 << endl;
for(int i = path.size() - 1; i >= 0; i--) {
cout << intToString[path[i]];
if(i != 0) {
cout << "->";
}
}
cout << endl;
return 0;
}

bool bellmanFord(int s) {
for(int i = 0; i < N; i++) {
d[i] = INF;
}
d[s] = 0;
for(int i = 0; i < N - 1; i++) {
for(int u = 0; u < N; u++) {
for(int v = 0; v < N; v++) {
if(graph[u][v] != INF) {
if(d[u] + graph[u][v] < d[v]) {
d[v] = d[u] + graph[u][v];
pre[v].clear();
pre[v].insert(u);
} else if(d[u] + graph[u][v] == d[v]) {
pre[v].insert(u);
}
}
}
}
}
for(int u = 0; u < N; u++) {
for(int v = 0; v < N; v++) {
if(graph[u][v] != INF) {
if(d[u] + graph[u][v] < d[v]) {
return false;
}
}
}
}
return true;
}

void dfs(int nowVisit) {
tempPath.push_back(nowVisit);
if(nowVisit == 0) {
count++;
int value1 = 0;
for(int i = tempPath.size() - 2; i >= 0; i--) {
value1 += happy[tempPath[i]];
}
double value2 = value1 * 1.0 / (tempPath.size() - 1);
if(value1 > optValue1) {
optValue1 = value1;
optValue2 = value2;
path = tempPath;
} else if(value1 == optValue1 && value2 > optValue2) {
optValue2 = value2;
path = tempPath;
}
tempPath.pop_back();
return;
}
set<int>::iterator it;
for(it = pre[nowVisit].begin(); it != pre[nowVisit].end(); it++){
dfs(*it);
}
tempPath.pop_back();
}``````

C++解题报告：

### 思路六：SPFA算法+深度优先遍历（邻接矩阵实现）

C++代码：

``````#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<set>
#include<queue>

using namespace std;

int N;	//城市数量
int K;	//道路条数
int INF = 1000000000;
string start;	//起始城市
int graph[201][201];
map<string, int> stringToInt;	//城市名称->城市编号
map<int, string> intToString;	//城市编号->城市名称
int happy[201];	//每个城市的快乐数
int d[201];
set<int> pre[201];
vector<int> tempPath;
vector<int> path;
int optValue1 = 0;
double optValue2 = 0;
int count = 0;
bool inq[201] = {false};
int countInq[201] = {0};

bool spfa(int s);
void dfs(int nowVisit);

int main() {
cin >> N >> K >> start;
stringToInt[start] = 0;	//起始城市编号为0
intToString[0] = start;
string city;
int happyness;
for(int i = 1; i < N; i++) {
cin >> city >> happyness;
stringToInt[city] = i;
intToString[i] = city;
happy[i] = happyness;
}
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
graph[i][j] = graph[j][i] = INF;
}
}
string city1, city2;
int cost;
for(int i = 0; i < K; i++) {
cin >> city1 >> city2 >> cost;
int id1 = stringToInt[city1];
int id2 = stringToInt[city2];
graph[id1][id2] = graph[id2][id1] = cost;
}
spfa(0);
int destination = stringToInt["ROM"];
dfs(destination);
cout << count << " " << d[destination] << " " << optValue1 << " " << (int)optValue2 << endl;
for(int i = path.size() - 1; i >= 0; i--) {
cout << intToString[path[i]];
if(i != 0) {
cout << "->";
}
}
cout << endl;
return 0;
}

bool spfa(int s) {
for(int i = 0; i < N; i++) {
d[i] = INF;
}
d[s] = 0;
queue<int> q;
q.push(s);
inq[s] = true;
countInq[s]++;
while(!q.empty()){
int u = q.front();
q.pop();
inq[u] = false;
for(int v = 0; v < N; v++){
if(graph[u][v] != INF){
if(d[u] + graph[u][v] < d[v]){
d[v] = d[u] + graph[u][v];
pre[v].clear();
pre[v].insert(u);
if(!inq[v]){
q.push(v);
inq[v] = true;
countInq[v]++;
if(countInq[v] >= N){
return false;
}
}
}else if(d[u] + graph[u][v] == d[v]){
pre[v].insert(u);
if(!inq[v]){
q.push(v);
inq[v] = true;
countInq[v]++;
if(countInq[v] >= N){
return false;
}
}
}
}
}
}
return true;
}

void dfs(int nowVisit) {
tempPath.push_back(nowVisit);
if(nowVisit == 0) {
count++;
int value1 = 0;
for(int i = tempPath.size() - 2; i >= 0; i--) {
value1 += happy[tempPath[i]];
}
double value2 = value1 * 1.0 / (tempPath.size() - 1);
if(value1 > optValue1) {
optValue1 = value1;
optValue2 = value2;
path = tempPath;
} else if(value1 == optValue1 && value2 > optValue2) {
optValue2 = value2;
path = tempPath;
}
tempPath.pop_back();
return;
}
set<int>::iterator it;
for(it = pre[nowVisit].begin(); it != pre[nowVisit].end(); it++){
dfs(*it);
}
tempPath.pop_back();
}``````

C++解题报告：