题目是让我们求一个无向图的最小环[周长最小],并将路径按照顺序打印出来
求无向图的最小环可以用floyd算法来求
打印路径可以有两种方法
(1)用pre[i][j] 数组表示 从i到j的路径中 最后松弛的节点,该节点一定在从i到j的路径中,然后递归求解
(2)通过枚举节点,如果满足dist[i][k] + dist[k][j] == dist[i][j],则说明k在从i到j的路径中,然后递归求解
(1)代码:
void create_end(int l, int r) {
int k = pre[l][r];
if(k == 0) {
end[len++] = r;
return ;
}
create_end(l, k);
create_end(k, r);
}
void floyd() {
int i, j, k;
answer = 100000000;
CLR(pre, 0);
FORE(i, 1, N) FORE(j, 1, N)
dist[i][j] = g[i][j];
FORE(k, 1, N) {
FOR(i, 1, k) FOR(j, i + 1, k)
if(answer > g[k][i] + g[k][j] + dist[i][j]) {
answer = g[k][i] + g[k][j] + dist[i][j];
len = 2;
end[0] = k;
end[1] = i;
create_end(i, j);
}
FORE(i, 1, N) FORE(j, 1, N)
if(dist[i][j] > dist[i][k] + dist[k][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
pre[i][j] = k;
}
}
if(answer == 100000000)
printf("No solution.\n");
else {
FOR(i, 0, len)
(i == 0) ? printf("%d", end[i]) : printf(" %d", end[i]);
printf("\n");
}
}
(2)代码:
/*
* POJ 1734 - Sightseeing Tree
*/
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstring>
#include <cstdio>
using namespace std;
#define FOR(i,a,b) for(i = (a); i < (b); ++i)
#define FORE(i,a,b) for(i = (a); i <= (b); ++i)
#define FORD(i,a,b) for(i = (a); i > (b); --i)
#define FORDE(i,a,b) for(i = (a); i >= (b); --i)
#define CLR(a,b) memset(a,b,sizeof(a))
const int MAXN = 110;
const int INF = 0x7f7f7f7f;
int k;
int N, M;
int answer;
int len;
int result[MAXN];
int g[MAXN][MAXN];
int dist[MAXN][MAXN];
void create_end(int l, int r) {
int i;
if(dist[l][r] == g[l][r]) {
result[len++] = r;
return ;
}
FOR(i, 1, k)
if(i != l && i != r && dist[l][i] + dist[i][r] == dist[l][r]) {
if(l == 40)
{
int stop = 0;
}
create_end(l, i);
create_end(i, r);
break;
}
}
void floyd() {
int i, j;
answer = 100000000;
FORE(i, 1, N) FORE(j, 1, N)
dist[i][j] = g[i][j];
FORE(k, 1, N) {
FOR(i, 1, k) FOR(j, i + 1, k)
if(answer > g[k][i] + g[k][j] + dist[i][j]) {
answer = g[k][i] + g[k][j] + dist[i][j];
len = 2;
result[0] = k;
result[1] = i;
create_end(i, j);
}
FORE(i, 1, N) FORE(j, 1, N)
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}
if(answer == 100000000)
printf("No solution.\n");
else {
FOR(i, 0, len)
(i == 0) ? printf("%d", result[i]) : printf(" %d", result[i]);
printf("\n");
}
}
void input() {
int i,j;
int a, b, l;
while(scanf("%d %d", &N, &M) != EOF) {
FORE(i, 1, N) FORE(j, 1, N)
g[i][j] = 100000000;
FORE(i, 1, M) {
scanf("%d %d %d", &a, &b, &l);
g[a][b] = g[b][a] = min(g[a][b], l);
}
floyd();
}
}
int main() {
input();
return 0;
}