题目链接:http://poj.org/problem?id=1502。
思路:这道题本质是求单源最短路径。Dijkstra算法解决,利用dist数组保存每个顶点到源点的最短路径,利用visited数组标示该顶点是否被访问,每一次更新dist时顺便找出未被访问点到源点的最短路径。代码实现如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 105;
const int INF = 0xfffffff;
int n, graph[MAXN][MAXN], dist[MAXN], visited[MAXN];
int str_to_price(char *str) {
int price = 0;
if (str[0] != 'x') {
for (int i = 0; i < strlen(str); i++) {
price = price*10 + (str[i]-'0');
}
return price;
}
return 0;
}
void Dijkstra() {
int curNode = 1, maxPrice = 0;
visited[curNode] = true;
dist[curNode] = 0;
for (int cnt = 2; cnt <= n; cnt++) {
int minDis = INF, minNode = 1;
for (int i = 1; i <= n; i++) {
if (!visited[i] && graph[curNode][i]) {
dist[i] = min(dist[i], (dist[curNode]+graph[curNode][i]));
if (dist[i] < minDis) {
minNode = i;
minDis = dist[i];
}
}
}
maxPrice = max(maxPrice, dist[minNode]);
curNode = minNode;
visited[minNode] = true;
}
cout << maxPrice << endl;
}
int main() {
char str[10];
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
dist[i] = INF;
visited[i] = false;
}
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
scanf("%s", str);
graph[j][i] = graph[i][j] = str_to_price(str);
}
}
Dijkstra();
return 0;
}
对于求单源最短路径问题,除了Dijkstra,还有一种算法那就是Bellman-Ford算法,不过这种算法效率没有Dijkstra高,但它能够用来解决Dijkstra无法解决的问题,比如图中含有负权边或者是负圈,只能够用Bellman-Ford算法来求解。但是对于这道题目用Bellman-Ford来求解的话会超时,下面是代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN = 6;
const int INF = 0xfffffff;
int n, graph[MAXN][MAXN], dist[MAXN], inQueen[MAXN];
queue<int> q;
int str_to_price(char *str) {
int price = 0;
if (str[0] != 'x') {
for (int i = 0; i < strlen(str); i++) {
price = price*10 + (str[i]-'0');
}
return price;
}
return 0;
}
void Bell_Ford() {
q.push(1);
inQueen[1] = true;
dist[1] = 0;
while (!q.empty()) {
int idx = q.front();q.pop();
inQueen[idx] = false;
for (int i = 1; i <= n; i++) {
if (graph[idx][i] && (dist[i] > graph[idx][i]+dist[idx])) {
dist[i] = graph[idx][i] + dist[idx];
//下面这两句可以用来判断一个图中是否含有负圈
//cnt[i] ++;
//if (cnt[i] == n) cout << "negetive circle" << endl;
if (!inQueen[i]) {
q.push(i);
inQueen[i] = true;
}
}
}
}
int ans = dist[1];
for (int i = 2; i <= n; i++) ans = max(ans, dist[i]);
cout << ans << endl;
}
int main() {
char str[10];
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
dist[i] = INF;
inQueen[i] = false;
}
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
scanf("%s", str);
graph[j][i] = graph[i][j] = str_to_price(str);
}
}
Bell_Ford();
return 0;
}