POJ 1734-Sightseeing trip

32 篇文章 0 订阅

题目是让我们求一个无向图的最小环[周长最小],并将路径按照顺序打印出来

求无向图的最小环可以用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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值