「POJ1734」Sightseeing trip

「POJ1734」Sightseeing trip

传送门
这题就是要我们求一个最小环并且按顺序输出一组解。
考虑 \(O(n^3)\) 地用 \(\text{Floyd}\) 求最小环:
考虑 \(\text{Floyd}\) 的过程,在最外层循环枚举到 \(k\) 时,最短路矩阵中,\(f_{i, j}\) 存储的就是 \(i\)\(j\) 经过点 \(1\cdots k - 1\) 的最短路。
那么我们就可以在这时枚举和点 \(k\) 相邻的两个点 \(i, j\)\(\min \left\{f_{i, j} + w(i, k) + w(j, k)\right\}\) 就是包含点 \(k\) 的最小环长度,然后再用点 \(k\) 更新最短路矩阵,取最小值即可。
对于路径的输出,只需要在更新最短路时记录一下中转点然后每次递归处理即可。
参考代码:

#include <cstring>
#include <cstdio>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < class T > inline T min(T a, T b) { return a < b ? a : b; }
template < class T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while ('0' > c || c > '9') f |= c == '-', c = getchar();
    while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
    s = f ? -s : s;
}

const int _ = 102;
typedef long long LL;

int n, m, d[_][_], f[_][_], p[_][_], G[_];

inline void dfs(int x, int y) {
    if (p[x][y] != 0) dfs(x, p[x][y]), G[++G[0]] = p[x][y], dfs(p[x][y], y);
}

int main() {
#ifndef ONLINE_JUDGE
    file("cpp");
#endif
    read(n), read(m);
    for (rg int i = 1; i <= n; ++i)
        for (rg int j = 1; j <= n; ++j) d[i][j] = 2147483647;
    for (rg int i = 1; i <= n; ++i) d[i][i] = 0;
    for (rg int u, v, l; m--; )
        read(u), read(v), read(l), d[u][v] = d[v][u] = min(d[u][v], l);
    for (rg int i = 1; i <= n; ++i)
        for (rg int j = 1; j <= n; ++j) f[i][j] = d[i][j];
    int ans = 2147483647;
    for (rg int k = 1; k <= n; ++k) {
        for (rg int i = 1; i < k; ++i)
            for (rg int j = 1; j < i; ++j) {
                if (ans > (LL) d[k][i] + f[i][j] + d[j][k]) {
                    ans = d[k][i] + f[i][j] + d[j][k];
                    G[0] = 0, G[++G[0]] = i, dfs(i, j), G[++G[0]] = j, G[++G[0]] = k;
                }
            }
        for (rg int i = 1; i <= n; ++i)
            for (rg int j = 1; j <= n; ++j)
                if (f[i][j] > (LL) f[i][k] + f[k][j])
                    f[i][j] = f[i][k] + f[k][j], p[i][j] = k;
    }
    if (ans == 2147483647) puts("No solution.");
    else for (rg int i = 1; i <= G[0]; ++i) printf("%d ", G[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zsbzsb/p/12190516.html