Ural 1004 FLOYD最小环问题
题目大意: 给出一些双向边, 求图中的一个最小环, 当u-v被选中时, v-u不能被选, 按顺序输出这个最小环, n<=100
无解则输出。
题目既然要求最小环,数据范围还这么小, 容易联想到FLOYD, 并且这里是双向边也没有什么关系, 因为只能选一条, 但题目比较麻烦的地方就是要输出这个环,
我的处理好像和机房的人不一样。。。。。
我想到的办法是对于每一个i -> j的路径, 记下最优的中间点, 再记下最小环中的最大序号点, 和最小环中的floyd的那一条路径的起点和终点, 递归输出。
开始一直WA#2, 一开始以为是我的FLOYD和网上主流的FLOYD不一样, 然而好像我的FLOYD那个细节地方貌似无关紧要, 然后突然发现有个BUG!!!! 因为我的最小环记下的路径是前k-1个点为中间点更新后的答案, 所以一种诡异的情况就是第k次恰好可以更新掉我记下的路径, 那么我输出的答案会有两个k点(手动滑稽。。。。)所以我就做了两遍, 先做出最小环再跑一遍FLOYD就ok
好像还可以用个vector来更新答案, 不过没我的方便hhhh
贴代码-----
#include <cstdio>
#include <cstring>
const int N = 100 + 10;
const int oo = 1e8 + 1e7 + 7e5;
#define min(a, b) a < b? a : b
#define rep(i, s, t) for(int i = s; i <= t; ++i)
int G[N][N], p[N], Mid, x, y, top;
int n, m, a[N][N], f[N][N], Ans[N];
void init() {
top = 0;
Mid = 0, x = 0, y = 0;
rep(i, 0, n) p[i] = 0;
rep(i, 0, n) rep(j, 0, n)
a[i][j] = f[i][j] = oo, G[i][j] = 0;
}
void dfs(int i, int j) {
if(a[i][j] == f[i][j]) {
if(!p[i]) Ans[++top] = i, p[i] = 1;
if(!p[j]) Ans[++top] = j, p[j] = 1;
return ;
}
dfs(i, G[i][j]), dfs(G[i][j], j);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
freopen("res.out", "w", stdout);
#endif
while(1) {
scanf("%d", &n);
if(n == -1) break;
scanf("%d", &m);
init();
rep(i, 1, m) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
a[u][v] = a[v][u] = min(a[u][v], w);
f[u][v] = f[v][u] = a[u][v];
}
rep(i, 0, n) a[i][i] = f[i][i] = 0;
int Res = oo;
rep(k, 1, n) {
rep(i, 1, k-1)
rep(j, 1, k-1)
if(i ^ j)
if(a[k][i] + a[j][k] + f[i][j] < Res)
Res = a[k][i] + a[j][k] + f[i][j];
rep(i, 1, n)
rep(j, 1, n)
if(f[i][k] + f[k][j] < f[i][j]) {
f[i][j] = f[i][k] + f[k][j];
G[i][j] = k;
}
}
if(Res >= oo) {
puts("No solution.");
continue;
}
bool flag = 0;
rep(i, 1, n) rep(j, 1, n) f[i][j] = a[i][j], G[i][j] = 0;
rep(k, 1, n) {
rep(i, 1, k-1) {
rep(j, 1, k-1)
if(i ^ j)
if(a[k][i] + a[j][k] + f[i][j] == Res) {
Mid = k, x = i, y = j;
flag = 1;
break;
}
if(flag) break;
}
if(flag) break;
rep(i, 1, n)
rep(j, 1, n)
if(f[i][k] + f[k][j] < f[i][j]) {
f[i][j] = f[i][k] + f[k][j];
G[i][j] = k;
}
}
p[Mid] = 1, Ans[++top] = Mid;
dfs(x, y);
rep(i, 1, top) printf("%d%c", Ans[i], i^top? ' ':'\n');
}
return 0;
}
看起来很长吧, 其实思路很清晰的。。。。。相信你们也不会来看我的这么丑的代码