zoukankan      html  css  js  c++  java
  • 【POJ1734】Sightseeing trip

    题目链接

    Sightseeing trip

    题目描述

    There is a travel agency in Adelton town on Zanzibar island. It has decided to offer its clients, besides many other attractions, sightseeing the town. To earn as much as possible from this attraction, the agency has accepted a shrewd decision: it is necessary to find the shortest route which begins and ends at the same place. Your task is to write a program which finds such a route.

    In the town there are N crossing points numbered from (1) to (N) and (M) two-way roads numbered from (1) to (M). Two crossing points can be connected by multiple roads, but no road connects a crossing point with itself. Each sightseeing route is a sequence of road numbers (y_1), ..., (y_k, k>2). The road (y_i) ((1 le i le k-1)) connects crossing points (x_i) and (x_{i+1}), the road (y_k) connects crossing points (x_k) and (x_1). All the numbers (x_1),...,(x_k) should be different.The length of the sightseeing route is the sum of the lengths of all roads on the sightseeing route, (i.e. L)((y_1))(+L)((y_2))(+...+L)((y_k)) where (L)((y_i)) is the length of the road (y_i) ((1 le i le k)). Your program has to find such a sightseeing route, the length of which is minimal, or to specify that it is not possible,because there is no sightseeing route in the town.

    输入格式

    The first line of input contains two positive integers: the number of crossing points (N le 100) and the number of roads (M le 10000). Each of the next (M) lines describes one road. It contains (3) positive integers: the number of its first crossing point, the number of the second one, and the length of the road (a positive integer less than (500)).

    输出格式

    There is only one line in output. It contains either a string '(No solution.)' in case there isn't any sightseeing route, or it contains the numbers of all crossing points on the shortest sightseeing route in the order how to pass them ((i.e.) the numbers (x_1) to (x_k) from our definition of a sightseeing route), separated by single spaces. If there are multiple sightseeing routes of the minimal length, you can output any one of them.

    样例输入

    5 7
    1 4 1
    1 3 300
    3 1 10
    1 2 16
    2 3 100
    2 5 15
    5 3 20
    

    样例输出

    1 3 5 2
    

    题解

    题意:给定一个无向图,求最短的环,顺序输出环上的每个点。
    如果直接暴力dfs找环,那么肯定会(T)的。
    我们考虑到最小环肯定是由两个节点的最短路和次短路组成。
    那么我们马上就想到了伟大的Floyd,只需要优良(O)((n^3))。
    假设我们用(s[j][i])(j)(i)的最短路。
    我们只要在每次更新之前把当前将要更新的路径(最短路)和(s[j][i])(次短路)加起来和答案取(min)就好了。
    因为最后一次更新之后(s[j][i])就是最短路了,所以更新之前是次短路。
    那么我们接下来就有这么一个问题了,怎么求路径。
    我们这里用(up[j][i])表示从(j)(i)的最短路,(i)的父亲是谁。
    那么我们每次更新的时候把(up)也更新上就好了。
    上代码:

    #include<cstdio>
    #include<string.h>
    using namespace std;
    int n,m,x,y,w;
    int to[109][109];
    int s[109][109];
    int up[109][109];
    int anss[109],ls,ans=-1;
    void dfs(){
        for(int k=1;k<=n;k++){
            for(int j=1;j<k;j++){
                for(int i=j+1;i<k;i++){
                    if(s[j][i]==-1 || to[j][k]==-1 || to[k][i]==-1) continue;
                    if(ans==-1 || ans>s[j][i]+to[j][k]+to[k][i]){
                        ans=s[j][i]+to[j][k]+to[k][i];
                        ls=0;
                        int u=i;
                        while(u!=j){
                            anss[++ls]=u;
                            u=up[j][u];
                        }
                        anss[++ls]=j;
                        anss[++ls]=k;//把当前最小环存到anss数组里
                    }
                }
            }
            for(int j=1;j<=n;j++)
                for(int i=1;i<=n;i++){
                    if(s[j][k]==-1 || s[k][i]==-1) continue;
                    if(s[j][i]==-1 || s[j][i]>s[j][k]+s[k][i]){
                        s[j][i]=s[j][k]+s[k][i];
                        up[j][i]=up[k][i];
                    }
                }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        memset(to,-1,sizeof(to));
        memset(s,-1,sizeof(s));
        for(int j=1;j<=m;j++){
            scanf("%d%d%d",&x,&y,&w);
            if(to[x][y]==-1 || to[x][y]>w) to[x][y]=to[y][x]=w;//注意重边
        }
        for(int j=1;j<=n;j++)
            for(int i=1;i<=n;i++){
                s[j][i]=to[j][i];
                up[j][i]=j;
            }
        dfs();
        if(ans==-1){
            printf("No solution.");
            return 0;
        }
        for(int j=1;j<=ls;j++)
            printf("%d ",anss[j]);
        return 0;
    }
    
  • 相关阅读:
    postfix发信提示 Error: too many connectino from
    postfix 设置邮件头翻译,本域邮件不进行邮件头翻译,仅发送至外网的进行邮件头翻译?
    postfix 如何设置邮件头翻译的功能
    postfix 如何设置邮件头翻译的功能
    Oracle VM VirtualBox如何设置网络地址转换NAT
    python提取百度经验<标题,发布时间,平均流量,总流量,具体的链接>
    css 需要阴影的效果
    django POST表单的使用
    Vim中如何使用正则进行搜索
    Nginx 如何设置反向代理
  • 原文地址:https://www.cnblogs.com/linjiale/p/13478649.html
Copyright © 2011-2022 走看看