Although literally, the secondary short circuit is the same as the 2nd short circuit. However, this is not what I encountered in my questions.
In some cases, you need to determine whether a short circuit exists. For example, there is only one path between u and v. Only the shortest path is short. The secondary short circuit does not exist. At this time, the solution is to first find the shortest path, then enumerate and delete the edges in the shortest path, and then find the minimum value. For more information, see poj3986.
The implementation of the K short circuit is the spfa + A * algorithm.
A * The algorithm uses an evaluation function f (h) to estimate the distance between the current vertex P and the end vertex, and thus determines the search direction. When this path fails, it will try other paths. For a *, the evaluation function = the current value + the distance from the current position to the end point, that is, f (p) = g (p) + H (P ), the minimum function value is estimated for each extension. For the K short circuit algorithm, g (P) is the length of the path from S to P, and h (P) is the shortest length from P to T, then f (p) indicates how far T should be taken from S to P based on the current path and then to the end.
Specific steps:
Use chained forward stars to store graphs. Because we need to pre-process the shortest paths from all vertices to the destination T, we need to echo all edges in graph G to get G1 and then perform the single-source shortest path from the destination T, so it is actually two images.
1. Reverse all edges of a directed graph. Take T (endpoint) as the source point and calculate the shortest distance from t to all points. In this step, the Dijkstra or spfa algorithm can be used.
2. Create a priority queue and add the Source Vertex s to the queue.
3. The minimum P value of f (p) is displayed in the priority queue. If P is t, the number of T queues is calculated. If the current value is K of T, the length of the current path is the nth short circuit from S to t, and the algorithm ends. Otherwise, traverse all the edges of the P necklace and add the expanded adjacent contact information to the priority queue.
Note: When S = t, the K + 1 short circuit must be calculated, so that the path from S to T is 0 and cannot be included in the K short circuit, in this case, you only need to add K to 1 and then calculate the K short circuit.
If there is only one path between U and V, the value of K short circuit is the same as that of the shortest path. We also need to know that if there is a circle between U and V, then k + 1 short circuit is more than K short circuit and the edge weight of this circle.
The template of K short circuit is as follows, and the time complexity is uncertain, but it is very efficient to know. You can use poj2449 for testing. You only need to add the header file and the main function.
const int N = 1010, M=100010;const int INF = 0x3f3f3f3f;struct node{ int to, w, next;};node edge[M],edge1[M];int head[N], dist[N], outq[N], head1[N], tot;bool vis[N];bool SPFA(int s, int n ){ int i,k; for(i=0;i<=n;i++) dist[i]=INF; memset(vis,0,sizeof(vis)); memset(outq,0,sizeof(outq)); queue<int > q; while(!q.empty()) q.pop(); vis[s]=1; dist[s]=0; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; outq[u]++; if(outq[u]>n) return 0 ; k=head1[u]; while(k>=0) { if(dist[edge1[k].to]-edge1[k].w>dist[u]) { dist[edge1[k].to]=dist[u]+edge1[k].w; if(!vis[edge1[k].to]) { vis[edge1[k].to]=1; q.push(edge1[k].to); } } k=edge1[k].next; } } return 1;}struct Node1{ int to; int g,f; bool operator<(const Node1 &r) const { if(r.f==f) return r.g<g; return r.f<f; }};int a_star(int start, int End, int k,int n){ Node1 e,ne; int cnt=0; priority_queue<Node1> que; while(!que.empty()) que.pop(); if(start==End) k++; if(dist[start]==INF) return -1; e.to=start; e.g=0; e.f=e.g+ dist[e.to]; que.push(e); while(!que.empty()) { e= que.top(); que.pop(); if(e.to==End) cnt++; if(cnt==k) return e.g; for(int i=head[e.to];i!=-1;i=edge[i].next) { ne.to=edge[i].to; ne.g=e.g+ edge[i].w; ne.f=ne.g+ dist[ne.to]; que.push(ne); } } return -1;}void addedge(int i,int j,int w){ edge[tot].to=j; edge[tot].w=w; edge[tot].next=head[i]; head[i]=tot++;}void init(){ tot=0; memset(head,-1,sizeof(head)); memset(head1,-1,sizeof(head1));}
Enumeration + the most short-circuit implementation an important step is to use a precursor to record the shortest path. You also need to mark the edges that belong to the shortest path.
const int N = 1010, M=100010;const int INF = 0x3f3f3f3f;struct node{ int u,to, w, next,flag;};node edge[M];int head[N], dist[N], outq[N];bool vis[N];int tot,flag,path[N];bool SPFA(int s, int n ){ int i,k; for(i=0;i<=n;i++) dist[i]=INF; memset(vis,0,sizeof(vis)); memset(outq,0,sizeof(outq)); queue<int > q; while(!q.empty()) q.pop(); vis[s]=1; dist[s]=0; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; outq[u]++; if(outq[u]>n) return 0 ; k=head[u]; while(k>=0) { if(edge[k].flag&&dist[edge[k].to]-edge[k].w>dist[u]) { dist[edge[k].to]=dist[u]+edge[k].w; if(!flag) path[edge[k].to]=k; if(!vis[edge[k].to]) { vis[edge[k].to]=1; q.push(edge[k].to); } } k=edge[k].next; } } return 1;}void addedge(int i,int j,int w){ edge[tot].u=i; edge[tot].to=j; edge[tot].w=w; edge[tot].flag=1; edge[tot].next=head[i]; head[i]=tot++;}void init(){ tot=0; memset(head,-1,sizeof(head)); memset(path,-1,sizeof(path));}
You can use poj3986 to test the template. Remember to add two sides, forward and reverse edges.
Next short circuit + K short circuit Template