删除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 ; }