河南第十届ACM省赛-I-Transmit information
2017-05-12 13:05
351 查看
ACM模版
这里是求经过 N 条边的最短路,简单的最短路算法已经无法满足需求,我们需要对图进行 N 次 Floyd,由于每次 Floyd 都不是直接对原花费矩阵操作,而是将值存在另一个矩阵中,所以可以保证每次 Floyd 都能够只收缩一条边,这样 N 次 Floyd 后就能保证通过了 N 条边获取的最短路。这里由于 Floyd 是 O(n3) 复杂度,所以进行 N 次 Floyd 显然是不现实的,这里我们可以利用矩阵快速幂的思路搞矩阵加速,这样就使其变为可行了。最后总复杂度为 O(n3logn),客观讲,这个解法不难理解,但是没有接触过的真是不好想到,具体代码十分容易看明白,就不多说了。
描述
题解
十分有趣的一道题,可以用 dp 解,也可以用倍增法 Floyd 解,标程是后者。这里是求经过 N 条边的最短路,简单的最短路算法已经无法满足需求,我们需要对图进行 N 次 Floyd,由于每次 Floyd 都不是直接对原花费矩阵操作,而是将值存在另一个矩阵中,所以可以保证每次 Floyd 都能够只收缩一条边,这样 N 次 Floyd 后就能保证通过了 N 条边获取的最短路。这里由于 Floyd 是 O(n3) 复杂度,所以进行 N 次 Floyd 显然是不现实的,这里我们可以利用矩阵快速幂的思路搞矩阵加速,这样就使其变为可行了。最后总复杂度为 O(n3logn),客观讲,这个解法不难理解,但是没有接触过的真是不好想到,具体代码十分容易看明白,就不多说了。
代码
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> using namespace std; const int MAXN = 1005; int k, m, s, t; int ans[MAXN][MAXN]; int tmp[MAXN][MAXN]; int tmp_[MAXN][MAXN]; int used[MAXN], v[MAXN], cnt; void floyd(int c[][MAXN], int a[][MAXN], int b[][MAXN]) { for (int k = 0; k < cnt; k++) { for (int i = 0; i < cnt; i++) { for (int j = 0; j < cnt; j++) { if (c[v[i]][v[j]] > a[v[i]][v[k]] + b[v[k]][v[j]]) { c[v[i]][v[j]] = a[v[i]][v[k]] + b[v[k]][v[j]]; } } } } } void copy(int a[][MAXN], int b[][MAXN]) { for (int i = 0; i < cnt; i++) { for (int j = 0; j < cnt; j++) { a[v[i]][v[j]] = b[v[i]][v[j]]; } } } void slove(int k) { while (k) { if (k & 1) { floyd(tmp_, ans, tmp); copy(ans, tmp_); memset(tmp_, 0x3f, sizeof(tmp_)); } floyd(tmp_, tmp, tmp); copy(tmp, tmp_); memset(tmp_, 0x3f, sizeof(tmp_)); k >>= 1; } } void init() { cnt = 0; memset(tmp, 0x3f, sizeof(tmp)); memset(tmp_, 0x3f, sizeof(tmp_)); memset(ans, 0x3f, sizeof(ans)); for (int i = 0; i < MAXN; i++) { ans[i][i] = 0; } } int main() { init(); scanf("%d%d%d%d", &k, &m, &s, &t); int x, y, w; for (int i = 0; i < m; i++) { scanf("%d%d%d", &w, &x, &y); if (!used[x]) { used[x] = 1; v[cnt++] = x; } if (!used[y]) { used[y] = 1; v[cnt++] = y; } if (tmp[x][y] > w) { tmp[x][y] = tmp[y][x] = w; } } slove(k); printf("%d\n", ans[s][t]); return 0; }
相关文章推荐
- 河南第十届ACM省赛-D-年终奖金
- 河南第十届ACM省赛-C-最小密钥
- 河南第十届ACM省赛-E-八纵八横
- 第十届河南acm省赛F: Binary to Prime
- D 年终奖金 河南第十届ACM真题 【dp】
- F Binary to Prime 河南第十届ACM真题 【模拟】
- ACM河南第八届省赛题
- G Plumbing the depth of lake 河南第十届ACM真题 【搜索】
- ACM河南第九届省赛题
- H Intelligent Parking Building 河南第十届ACM真题 【模拟】
- 第十届ACM省赛-C 最小秘钥
- 第十届ACM省赛-F Binary to Prime
- 第十届ACM省赛-E Plumbing the depth of lake
- 河南省第十届ACM省赛G:Plumbing the depth of lake
- 第十届河南 ACM 省赛纪事
- A 谍报分析 河南第十届ACM真题 【字符串处理】
- B 情报传递 河南第十届ACM真题 【图】
- 河南省第十届acm省赛-谍报分析——个人c++解
- C 最小密钥 河南第十届ACM真题 【模拟】
- 2015河南ACM省赛 - 小记