URAL_1004
可以枚举起点和终点做O(N^2)次dij,也可以用floyd直接求最小环,但是用floyd的效率要高一些。
#include<stdio.h> #include<string.h> #define MAXD 110 #define MAXM 20010 #define INF 0x3f3f3f3f int N, M, D, first[MAXD], next[MAXM], e, v[MAXM], w[MAXM], dis[MAXD]; int tree[4 * MAXD], q[MAXD], res, n, p[MAXD]; void add(int x, int y, int z) { v[e] = y, w[e] = z; next[e] = first[x]; first[x] = e ++; } void init() { int i, j, k, x, y, z; memset(first, -1, sizeof(first)); e = 0; for(i = 0; i < M; i ++) { scanf("%d%d%d", &x, &y, &z); add(x, y, z), add(y, x, z); } } void update(int i) { for(; i ^ 1; i >>= 1) tree[i >> 1] = dis[tree[i]] <= dis[tree[i ^ 1]] ? tree[i] : tree[i ^ 1]; } void solve() { int i, j, k, x, y, t, ok, f, S, T; for(D = 1; D < N + 2; D <<= 1); res = INF; for(S = 1; S <= N; S ++) for(e = first[S]; e != -1; e = next[e]) { T = v[e]; memset(tree, 0, sizeof(tree)); memset(dis, 0x3f, sizeof(dis)); dis[S] = p[S] = 0; for(i = first[S]; i != -1; i = next[i]) if(v[i] != T) { tree[D + v[i]] = v[i]; dis[v[i]] = w[i], p[v[i]] = S; update(D + v[i]); } while(tree[1] != 0) { x = tree[1]; if(x == T) break; tree[D + x] = 0, update(D + x); for(j = first[x]; j != -1; j = next[j]) { t = dis[x] + w[j], y = v[j]; if(t < dis[y]) { dis[y] = t, p[y] = x; tree[D + y] = y, update(D + y); } } } if(dis[T] != INF && dis[T] + w[e] < res) { res = dis[T] + w[e]; for(i = T, n = 0; i != 0; i = p[i]) q[n ++] = i; } } if(res == INF) printf("No solution.\n"); else { printf("%d", q[0]); for(i = 1; i < n; i ++) printf(" %d", q[i]); printf("\n"); } } int main() { for(;;) { scanf("%d", &N); if(N == -1) break; scanf("%d", &M); init(); solve(); } return 0; }
#include<stdio.h> #include<string.h> #define MAXD 110 #define INF 0x3f3f3f3f int N, M, g[MAXD][MAXD], f[MAXD][MAXD], p[MAXD][MAXD]; int q[MAXD], n; void init() { int i, j, k, x, y, z; memset(f, 0x3f, sizeof(f)); memset(g, 0x3f, sizeof(g)); for(i = 0; i < M; i ++) { scanf("%d%d%d", &x, &y, &z); if(z < g[x][y]) f[x][y] = f[y][x] = g[x][y] = g[y][x] = z, p[x][y] = y, p[y][x] = x; } } int Min(int x, int y) { return x < y ? x : y; } void solve() { int i, j, k, x, ans = INF; for(k = 1; k <= N; k ++) { for(i = 1; i < k; i ++) if(g[i][k] < ans) for(j = i + 1; j < k; j ++) if(g[k][j] < ans && f[i][j] + g[i][k] + g[k][j] < ans) { ans = f[i][j] + g[i][k] + g[k][j]; n = 0, x = i; while(x != j) { q[n ++] = x; x = p[x][j]; } q[n ++] = j; q[n ++] = k; } for(i = 1; i <= N; i ++) for(j = 1; j <= N; j ++) if(f[i][k] + f[k][j] < f[i][j]) f[i][j] = f[i][k] + f[k][j], p[i][j] = p[i][k]; } if(ans == INF) printf("No solution.\n"); else { printf("%d", q[0]); for(i = 1; i < n; i ++) printf(" %d", q[i]); printf("\n"); } } int main() { for(;;) { scanf("%d", &N); if(N == -1) break; scanf("%d", &M); init(); solve(); } return 0; }