zoukankan      html  css  js  c++  java
  • poj 1734 Sightseeing trip

    Time Limit: 1000MS Memory Limit: 65536K
    Total Submissions: 7827 Accepted: 2956 Special Judge

    Description
    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<=i<=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<=i<=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.

    Input
    The first line of input contains two positive integers: the number of crossing points N<=100 and the number of roads M<=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).

    Output
    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.

    Sample Input

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

    Sample Output

    1 3 5 2

    解题思路

    lyd书上的题,大意是找一个无向图里最小的环,因为n很小,考虑floyd。
    floyd的过程是找到i,j中间的某一点k,用dis[i][k]+dis[k][j]来更新dis[i][j] 。
    我们重新定义dis[i][j]为编号不超过k的最短路长度,我们每次选取k两边的点i,j,看是否dis[i][j]+a[i][k]+a[k][j]最小,为什么不可能是a[i][k]+a[k][j]作为dis[i][j] 呢,因为此时的dis[i][j]还没有用此时枚举的k来更新,如果最小就记录答案。边寻找最小环是也要边更新dis的值。
    记录环非常的巧妙,每次更新dis[i][j] 的值时要记录一个pos[i][j] = k,意思是i,j这两个点是由中间的点k来更新,这样的话就用递归的方法来更新。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #define LL long long
    
    using namespace std;
    const int MAXN = 105;
    const int inf = 0x3f3f3f3f;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-48;ch=getchar();}
        return x*f;
    }
    
    int n,m,ans=inf;
    int a[MAXN][MAXN];
    int pos[MAXN][MAXN];
    int dis[MAXN][MAXN];
    vector<int> path;
    
    inline void get_path(int x,int y){
        if(!pos[x][y]) return;
        get_path(x,pos[x][y]); //相当于继续寻找i,k之间由哪个点更新。
        path.push_back(pos[x][y]);
        get_path(pos[x][y],y);  //这时的y是上一次的pos[x][y]
    }
    
    inline void floyd(){
        for(register int k=1;k<=n;k++){
            for(register int i=1;i<k;i++)
                for(register int j=i+1;j<k;j++)
                    if((LL)dis[i][j]+a[i][k]+a[k][j]<ans){  //要开LL
                        ans=dis[i][j]+a[i][k]+a[k][j];
                        path.clear();
                        path.push_back(i);
                        get_path(i,j);
                        path.push_back(j);
                        path.push_back(k);
                    }
            for(register int i=1;i<=n;i++)  //更新dis值
                for(register int j=1;j<=n;j++)
                    if(dis[i][j]>dis[i][k]+dis[k][j]){
                        dis[i][j]=dis[i][k]+dis[k][j];
                        pos[i][j]=k;
                    }
        }
    
    }
    
    int main(){
        memset(a,0x3f,sizeof(a));
        n=rd();m=rd();
        for(register int i=1;i<=n;i++) a[i][i]=0;
        for(register int i=1;i<=m;i++){
            int x=rd(),y=rd(),z=rd();
            a[x][y]=a[y][x]=min(a[x][y],z);
        }
        memcpy(dis,a,sizeof(a));
        floyd();
        if(ans==inf) {
            puts("No solution.");
            return 0;
        }
        for(register int i=0;i<path.size();i++)
            printf("%d ",path[i]);
        return 0;
    }
  • 相关阅读:
    让owncloud成为微博式记事本
    软件即抽象
    十年,最后一个alpha,0.4.1版的reactos终于变得可赏可玩了
    使用群晖作mineportalbox(1):合理且不折腾地使用群晖硬件和套件
    使用群晖作mineportalbox(2):把webstation打造成snippter空间
    使用群晖作mineportalbox(3):在阿里云上单盘安装群晖skynas
    统一的分布式数据库和文件系统mongodb,及其用于解决aliyun上做站的存储成本方案
    吃桃
    1020: C语言程序设计教程(第三版)课后习题6.9
    分数序列
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676967.html
Copyright © 2011-2022 走看看