裸的无向图最小环,我们可以在Floyd的过程中求得。
具体思想是:枚举环中的编号最大的顶点k,然后枚举和k相关联的两个顶点i和j(i和j都小于k),则该环的长度为:dist[i][j] + g[j][k] + g[k][i],循环到k的时候,dist[i][j]表示的是i到j的经过的顶点编号小于k的最短路,所以正确性很显然,由于i、j、k都不相同,所以环上至少是3个点。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int INF = 999999; 7 const int N = 101; 8 int dist[N][N]; 9 int g[N][N]; 10 int n, m, ans; 11 12 void floyd() 13 { 14 for ( int i = 1; i <= n; i++ ) 15 { 16 for ( int j = 1; j <= n; j++ ) 17 { 18 dist[i][j] = g[i][j]; 19 } 20 dist[i][i] = g[i][i] = 0; 21 } 22 ans = INF; 23 for ( int k = 1; k <= n; k++ ) 24 { 25 for ( int i = 1; i < k; i++ ) 26 { 27 for ( int j = i + 1; j < k; j++ ) 28 { 29 int tmp = dist[i][j] + g[i][k] + g[k][j]; 30 if ( tmp < ans ) ans = tmp; 31 } 32 } 33 for ( int i = 1; i <= n; i++ ) 34 { 35 for ( int j = 1; j <= n; j++ ) 36 { 37 int tmp = dist[i][k] + dist[k][j]; 38 if ( tmp < dist[i][j] ) 39 { 40 dist[i][j] = tmp; 41 } 42 } 43 } 44 } 45 } 46 47 int main () 48 { 49 while ( scanf("%d%d", &n, &m) != EOF ) 50 { 51 for ( int i = 1; i <= n; i++ ) 52 { 53 for ( int j = 1; j <= n; j++ ) 54 { 55 g[i][j] = INF; 56 } 57 } 58 while ( m-- ) 59 { 60 int a, b, c; 61 scanf("%d%d%d", &a, &b, &c); 62 if ( c < g[a][b] ) 63 { 64 g[a][b] = g[b][a] = c; 65 } 66 } 67 floyd(); 68 if ( ans == INF ) 69 { 70 printf("It's impossible. "); 71 } 72 else 73 { 74 printf("%d ", ans); 75 } 76 } 77 return 0; 78 }