题目链接
A 算法7-15:迪杰斯特拉最短路径算法
- Dijkstra 算法,很简单啦。参考代码如下。
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 60;
const int INF = 0x3fffffff;
int G[MAXN][MAXN];
int n, s;
int d[MAXN];
bool vis[MAXN] = { false };
void dijkstra(){
fill(d, d + MAXN, INF);
d[s] = 0;
for (int i = 0; i < n; i++) {
int u = -1, MIN = INF;
for(int j=0;j<n;j++)
if (!vis[j] && d[j] < MIN) {
u = j;
MIN = d[j];
}
if (u == -1) return;
vis[u] = true;
for (int v = 0; v < n; v++)
if (!vis[v] && G[u][v] && d[u] + G[u][v] < d[v])
d[v] = d[u] + G[u][v];
}
}
int main() {
cin >> n >> s;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> G[i][j];
dijkstra();
bool first = true;
for(int i=0;i<n;i++)
if (i != s) {
if (!first) cout << ' ';
if (d[i] != INF)
cout << d[i];
else cout << -1;
first = false;
}
return 0;
}
B 算法7-16:弗洛伊德最短路径算法
- 需要先处理一下邻接矩阵,将值为 0 的权值设置为 INF(不可达),最后输出的时候要将值为 INF 的权值输出为 -1。参考代码如下。
#include<iostream>
using namespace std;
const int MAXN = 60;
const int INF = 0x3fffffff;
int G[MAXN][MAXN], n;
void floyd() {
for (int k = 0; k < n; k++)
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (G[i][k] != INF && G[k][j] != INF && G[i][k] + G[k][j] < G[i][j])
G[i][j] = G[i][k] + G[k][j];
}
int main() {
cin >> n;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
cin >> G[i][j];
if (i != j && G[i][j] == 0)
G[i][j] = INF;
}
floyd();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
if (G[i][j] == INF)
cout << -1 << ' ';
else cout << G[i][j] << ' ';
cout << endl;
}
return 0;
}
C 最短路径(未通过)
- 这道题结合了最短路径算法和大整数,结点的权值为,k 最大为500,因此如何表示权值是一个问题。不能把权值在输入的时候就模10万,那样在算最短路径的时候的权值已经不对了,最后算出来的最短路径肯定也就不对了。
- 这里想到的办法是用二进制串表示权值,模拟大整数运算。两个权值相加则为二进制串的相加,权值比较大小则为二进制串比较大小,具体思路见代码,可能写得比较复杂。
- 最后 d 数组存储的二进制串即为最短路径,直接把二进制串转换为十进制数再模10万就是最后的最短路径了。
- 很奇怪,不管怎么调试就是过不了。
//未通过
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
const int MAXN = 110;
const string INF = "2";
const int MOD = 100000;
int n, m;
struct node { int v; string dis; node(int v, string d) :v(v), dis(d) {} };
vector <node> adj[MAXN];
bool vis[MAXN] = { false };
string d[MAXN];
string add(string a, string b) {
if (a.size() < b.size()) swap(a, b);
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
for (int i = 0; i < b.size(); i++) {
a[i] += b[i] - '0';
if (a[i] > '1') {
a[i] -= 2;
if (i == a.size() - 1) a += "0";
a[i + 1]++;
}
}
reverse(a.begin(), a.end());
return a;
}
bool cmp_less(string a, string b) {
if (a == INF) return false;
else if (b == INF) return true;
else if (a.size() == b.size()) return a < b;
else if (a.size() < b.size()) return true;
else return false;
}
int pow(string s) {
reverse(s.begin(), s.end());
int t = 1, ans = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '1')
ans += t;
t = 2 * t % MOD;
}
return ans % MOD;
}
void dijkstra() {
fill(d, d + MAXN, INF);
d[0] = "0";
for (int i = 0; i < n; i++) {
int u = -1;
string MIN = INF;
for (int j = 0; j < n; j++)
if (!vis[j] && cmp_less(d[j], MIN)) {
u = j;
MIN = d[j];
}
if (u == -1) return;
vis[u] = true;
for (int j = 0; j < adj[u].size(); j++) {
int v = adj[u][j].v;
string dis = adj[u][j].dis;
if (!vis[v] && cmp_less(add(d[u], dis), d[v]))
d[v] = add(d[u], dis);
}
}
}
int main() {
cin >> n >> m;
int u, v;
string dis = "1";
while (m--) {
cin >> u >> v;
adj[u].push_back(node(v, dis));
adj[v].push_back(node(u, dis));
dis += "0";
}
dijkstra();
for (int i = 1; i < n; i++)
if (d[i] != INF)
cout << pow(d[i]) << endl;
else cout << -1 << endl;
return 0;
}
D 最短路径
- 简单题。但是不知道为什么邻接矩阵过不了,邻接表就能过(o((⊙﹏⊙))o)。参考代码如下。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 1010;
const int INF = 0x3fffffff;
struct node {
int v, dis;
node(int v, int d) :v(v), dis(d) {}
};
int n, m, s, t;
vector <node> adj[MAXN];
int d[MAXN], pre[MAXN];
bool vis[MAXN] = { false };
void dijkstra() {
fill(d, d + MAXN, INF);
fill(vis, vis + MAXN, false);
for (int i = 1; i <= n; i++) pre[i] = i;
d[s] = 0;
for (int i = 0; i < n; i++) {
int u = -1, MIN = INF;
for (int j = 1; j <= n; j++)
if (!vis[j] && d[j] < MIN) {
u = j;
MIN = d[j];
}
if (u == -1) return;
vis[u] = true;
for (int j= 0; j < adj[u].size(); j++) {
int v = adj[u][j].v;
int dis = adj[u][j].dis;
if (!vis[v]) {
if (d[u] + dis < d[v]) {
d[v] = d[u] + dis;
pre[v] = u;
}
else if (d[u] + dis == d[v] && pre[v] > u)
pre[v] = u;
}
}
}
}
void dfs(int v) {
if (v == s) {
cout << v << ' ';
return;
}
else {
dfs(pre[v]);
cout << v << ' ';
}
}
int main() {
while (cin >> n >> m >> s >> t) {
for (int i = 1; i <= n; i++)
adj[i].clear();
for (int i = 0; i < m; i++) {
int c1, c2, d;
cin >> c1 >> c2 >> d;
adj[c1].push_back(node(c2, d));
adj[c2].push_back(node(c1, d));
}
dijkstra();
if (d[t] == INF)
cout << "can't arrive" << endl;
else {
cout << d[t] << endl;
dfs(t);
cout << endl;
}
}
return 0;
}
E 最短路径问题
- 直接套用 Dijkstra + DFS 模板即可。参考代码如下。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 1010;
const int INF = 0x3fffffff;
struct node {
int v, dis;
node(int v, int d) :v(v), dis(d) {}
};
vector <node> adj[MAXN];
int cost[MAXN][MAXN], d[MAXN];
vector <int> pre[MAXN];
vector <int> temp_path;
int min_cost;
bool vis[MAXN];
int n, m, s, t;
void dijkstra() {
fill(d, d + MAXN, INF);
fill(vis, vis + MAXN, false);
d[s] = 0;
for (int i = 0; i < n; i++) {
int u = -1, MIN = INF;
for (int j = 1; j <= n; j++)
if (!vis[j] && d[j] < MIN) {
u = j;
MIN = d[j];
}
if (u == -1) return;
vis[u] = true;
for (int j = 0; j < adj[u].size(); j++) {
int v = adj[u][j].v;
int dis = adj[u][j].dis;
if (!vis[v]) {
if (d[u] + dis < d[v]) {
d[v] = d[u] + dis;
pre[v].clear();
pre[v].push_back(u);
}
else if (d[u] + dis == d[v])
pre[v].push_back(u);
}
}
}
}
void dfs(int v) {
if (v == s) {
temp_path.push_back(v);
int temp_cost = 0;
for (int i = temp_path.size() - 1; i > 0; i--)
temp_cost += cost[temp_path[i]][temp_path[i - 1]];
if (temp_cost < min_cost)
min_cost = temp_cost;
temp_path.pop_back();
}
temp_path.push_back(v);
for (int i = 0; i < pre[v].size(); i++)
dfs(pre[v][i]);
temp_path.pop_back();
}
int main() {
while (cin >> n >> m && n + m) {
for (int i = 1; i <= n; i++)
adj[i].clear();
for (int i = 1; i <= n; i++)
pre[i].clear();
fill(cost[0], cost[0] + MAXN * MAXN, INF);
min_cost = INF;
for (int i = 1; i <= m; i++) {
int a, b, d, p;
cin >> a >> b >> d >> p;
cost[a][b] = cost[b][a] = p;
adj[a].push_back(node(b, d));
adj[b].push_back(node(a, d));
}
cin >> s >> t;
dijkstra();
dfs(t);
cout << d[t] << ' ' << min_cost << endl;
}
return 0;
}