无负权边,所以可以用dijstra来求次短路,过程和求最短路一样,反复揣摩求次短路的过程有助于更深入的理解dijstra。
O(n^2)的写法(500ms):
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const int INF = 9999999; 8 const int N = 5001; 9 const int M = 200000; 10 int head[N]; 11 int dist[N][2]; 12 bool visit[N][2]; 13 int n, m, e; 14 15 struct Edge 16 { 17 int v, next, w; 18 } edge[M]; 19 20 void addEdge( int u, int v, int w ) 21 { 22 edge[e].v = v; 23 edge[e].w = w; 24 edge[e].next = head[u]; 25 head[u] = e++; 26 } 27 28 void dij( int s ) 29 { 30 memset( visit, false, sizeof(visit) ); 31 memset( dist, 0x3f, sizeof(dist) ); 32 dist[s][0] = 0; 33 for ( int i = 1; i <= 2 * n; i++ ) 34 { 35 int u, flag, mincost = INF; 36 for ( int j = 1; j <= n; j++ ) 37 { 38 for ( int k = 0; k <= 1; k++ ) 39 { 40 if ( !visit[j][k] && dist[j][k] < mincost ) 41 { 42 mincost = dist[j][k]; 43 u = j; 44 flag = k; 45 } 46 } 47 } 48 visit[u][flag] = 1; 49 for ( int j = head[u]; j != -1; j = edge[j].next ) 50 { 51 int v = edge[j].v, w = edge[j].w; 52 if ( !visit[v][0] && dist[v][0] > dist[u][flag] + w ) 53 { 54 dist[v][1] = dist[v][0]; 55 dist[v][0] = dist[u][flag] + w; 56 } 57 else if ( !visit[v][1] && dist[v][1] > dist[u][flag] + w ) 58 { 59 dist[v][1] = dist[u][flag] + w; 60 } 61 } 62 } 63 } 64 65 int main () 66 { 67 while ( scanf("%d%d", &n, &m) != EOF ) 68 { 69 e = 0; 70 memset( head, -1, sizeof(head) ); 71 while ( m-- ) 72 { 73 int u, v, w; 74 scanf("%d%d%d", &u, &v, &w); 75 addEdge( u, v, w ); 76 addEdge( v, u, w ); 77 } 78 dij(1); 79 printf("%d ", dist[n][1]); 80 } 81 return 0; 82 }
优先队列优化的写法(110ms):
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <queue> 6 using namespace std; 7 8 const int INF = 9999999; 9 const int N = 5001; 10 const int M = 200000; 11 int head[N]; 12 int dist[N][2]; 13 bool visit[N][2]; 14 int n, m, e; 15 16 struct Edge 17 { 18 int v, next, w; 19 } edge[M]; 20 21 void addEdge( int u, int v, int w ) 22 { 23 edge[e].v = v; 24 edge[e].w = w; 25 edge[e].next = head[u]; 26 head[u] = e++; 27 } 28 29 struct Node 30 { 31 int nn, tt, len; 32 Node(){} 33 Node( int _nn, int _tt, int _len ) 34 { 35 nn = _nn, tt = _tt, len = _len; 36 } 37 bool operator < ( const Node & o ) const 38 { 39 return len > o.len; 40 } 41 }; 42 43 priority_queue<Node> q; 44 45 void dij( int s ) 46 { 47 memset( visit, 0, sizeof(visit) ); 48 memset( dist, 0x3f, sizeof(dist) ); 49 dist[s][0] = 0; 50 q.push( Node( s, 0, 0 ) ); 51 while ( !q.empty() ) 52 { 53 Node cur = q.top(); 54 q.pop(); 55 if ( visit[cur.nn][cur.tt] ) continue; 56 visit[cur.nn][cur.tt] = true; 57 for ( int i = head[cur.nn]; i != -1; i = edge[i].next ) 58 { 59 int v = edge[i].v, w = edge[i].w; 60 if ( !visit[v][0] && cur.len + w < dist[v][0] ) 61 { 62 dist[v][1] = dist[v][0]; 63 dist[v][0] = cur.len + w; 64 q.push( Node( v, 1, dist[v][1] ) ); 65 q.push( Node( v, 0, dist[v][0] ) ); 66 } 67 else if ( !visit[v][1] && cur.len + w < dist[v][1] ) 68 { 69 dist[v][1] = cur.len + w; 70 q.push( Node( v, 1, dist[v][1] ) ); 71 } 72 } 73 } 74 } 75 76 int main () 77 { 78 while ( scanf("%d%d", &n, &m) != EOF ) 79 { 80 e = 0; 81 memset( head, -1, sizeof(head) ); 82 while ( m-- ) 83 { 84 int u, v, w; 85 scanf("%d%d%d", &u, &v, &w); 86 addEdge( u, v, w ); 87 addEdge( v, u, w ); 88 } 89 dij(1); 90 printf("%d ", dist[n][1]); 91 } 92 return 0; 93 }
优化了速度就是不一样!