zoukankan      html  css  js  c++  java
  • ural Sightseeing Trip(最短环)

    删除A、B点之间的连线,然后求两点间的最短路,如果有最短路,加上A、B之间的长度求最小值,就是所要求的最短环。但是还要求输出路径,我是用Spfa求最短路的,同时记录路径。

    用这种方法做完之后,看到discuss里有许多用floyd求最短环的,就上网搜了一下。原来可以直接用floyd在O(n^3)的时间里求最短环,但是这个标记路径有点麻烦,最终也没想出比较好的记录路径的方法,但是的确求出了最短环。

    spfa求最短路算法:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <math.h>
    #include <map>
    #include <stack>
    #include <vector>
    #define  N 104
    #define  INF 1000000000
    using namespace std ;
    
    int mp[N][N] , pre[N] , step[N] ;
    int dis[N] , n , m , ans ;
    bool f[N] ;
    queue<int>q ;
    
    void init()
    {
        memset( f , false , sizeof( f )) ;
        memset( pre , -1 , sizeof ( pre )) ;
        for ( int i = 0 ; i <= n ; i++ )
        dis[i] = INF ;
        while( !q.empty()) q.pop();
    }
    
    int Spfa( int s , int e )
    {
        init() ;
        f[s] = true ;
        dis[s] = 0 ;
        q.push( s ) ;
    
        while ( !q.empty())
        {
            int u = q.front() ;
            q.pop();
            f[u] = false ;
    
            for ( int i = 1 ; i <= n ; i++ )
            {
                if ( mp[u][i] < INF && dis[i] > dis[u] + mp[u][i] )
                {
                    dis[i] = dis[u] + mp[u][i] ;
                    pre[i] = u ;
    
                    if ( !f[i] )
                    {
                        f[i] = true ;
                        q.push( i ) ;
                    }
                }
            }
        }
        return dis[e] ;
    }
    
    void output( int x )
    {
        if ( step[x] == -1 )
        return ;
    
        output( step[x] ) ;
        printf ( "%d " , step[x] ) ;
        return ;
    }
    
    int main()
    {
        int i , j , x , y , z ;
    
        while ( scanf ( "%d" , &n ) , n != -1 )
        {
            for ( i = 0 ; i <= n ; i++ )
            {
                for ( j = 0 ; j <= n ; j++ )
                mp[i][j] = INF ;
            }
            scanf ( "%d" , &m ) ;
            for( i = 1 ; i <= m ; i++ )
            {
                scanf ( "%d%d%d" , &x , &y , &z ) ;
                if ( mp[x][y] > z )
                mp[x][y] = mp[y][x] = z ;
            }
    
            memset( step , -1 , sizeof ( step )) ;
            int pos = -1 ;
            ans = INF ;
            for ( i = 1 ; i <= n ; i++ )
            {
                for ( j = 1 ; j <= n ; j++ )
                {
                    if ( mp[i][j] < INF )
                    {
                        z = mp[i][j] ;
                        mp[i][j] = mp[j][i] = INF ;
                        y = Spfa( j , i ) + z ;
                        if ( y < ans )
                        {
                            ans = y ;
                            pos = i ;
                            for ( x = 1 ; x <= n ; x++ )
                            step[x] = pre[x] ;
                        }
                    }
                }
            }
            if( pos == -1 )
            {
                printf ( "No solution.\n" ) ;
            }
            else
            {
                output( pos ) ;
                printf ( "%d\n" , pos ) ;
            }
        }
        return 0 ;
    }

    在第一个样例处wa了好几次,不知道为什么,不知道是不是和路径输出的顺序有关,但是我将路径输出顺序改的和样例输出一样照样wa,弄得我万分郁闷。。。。。。

    floyd求最短环(无输出路径)

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <math.h>
    #include <map>
    #include <stack>
    #include <vector>
    #define  N 104
    #define  INF 1000000000
    using namespace std ;
    
    int dis[N][N] , grap[N][N] ;
    int n , m , ans ;
    int path[N][N] ;
    
    void output( int s , int e )
    {
        if ( s == e )
        return ;
        if ( path[s][e] == -1 )
        {
            printf ( " %d" , e ) ;
            return ;
        }
        else
        {
            output( s , path[s][e] ) ;
            output( path[s][e] , e ) ;
        }
    }
    
    int main()
    {
        int i , j , k , x , y , z ;
    
        while ( scanf ( "%d" , &n ) , n != -1 )
        {
            for ( i = 1 ; i <= n ; i++ )
            {
                for ( j = 1 ; j <= n ; j++ )
                {
                    dis[i][j] = grap[i][j] = INF ;
                    path[i][j] = -1 ;
                }
            }
    
            scanf ( "%d" , &m ) ;
            for ( i = 1 ; i <= m ; i++ )
            {
                scanf ( "%d%d%d" , &x , &y , &z ) ;
                if ( grap[x][y] > z )
                {
                    grap[x][y] = grap[y][x] = z ;
                    dis[x][y] = dis[y][x] = z ;
                }
            }
    
            //int s , e ;
            ans = INF ;
            for ( k = 1 ; k <= n ; k++ )
            {
                for ( i = 1 ; i < k ; i++ )
                {
                    for ( j = 1 ; j < i ; j++ )
                    if( ans > dis[i][j] + grap[i][k] + grap[k][j] )
                    {
                        ans = dis[i][j] + grap[i][k] + grap[k][j] ;
                        //path[i][j] = k ;
                        //s = j ; e = i ;
                    }
                }
    
                for ( x = 1 ; x <= n ; x++ )
                {
                    for ( y = 1 ; y < x ; y++ )
                    if( dis[x][k] + dis[k][y] < dis[x][y] )
                    {
                        dis[x][y] = dis[x][k] + dis[k][y] ;
                        //path[x][y] = k ;
                    }
                }
            }
    
            if ( ans == INF )
            cout<<"No solution."<<endl ;
            else
            {
                /*i = 0 ;
                int step[N] ;
                for ( k = s ; k != e ; k = path[k][e] )
                {
                    step[i++] = k ;
                }
                step[i++] = e ;
                step[i++] = k ;
    
                for ( j = 0 ; j < i ; j++ )
                cout<<step[j]<<" ";
                cout<<endl;*/
                cout<<ans<<endl ;
            }
        }
        return 0 ;
    }
  • 相关阅读:
    有趣的网站
    Python-Day2
    C# EF增删改查
    LINQ教程
    命名空间“System.Web”中不存在类型或命名空间名称“Optimization”(是否缺少程序集引用?)
    Log4Net组件的应用详解
    log4net应用
    Select count(*)和Count(1)的区别和执行方式
    Ms sql 2005 中的bit 数据类型
    关于CLR、CIL、CTS、CLS、CLI、BCL和FCL
  • 原文地址:https://www.cnblogs.com/misty1/p/2877272.html
Copyright © 2011-2022 走看看