题目大意:求图的严格次短路。
方法1:
SPFA,同时求单源最短路径和单源次短路径。站在节点u上放松与其向量的v的次短路径时时,先尝试由u的最短路径放松,再尝试由u的次短路径放松(该两步并非非此即彼)。
由u的最短路径放松:
if(u->Dist + e->Weight < v->Dist) v->Dist2=v->Dist; //此处隐藏最短路放松。次短路不在此固定,Dist2可能在由u次短路放松时被放松得更短 if(u->Dist + e->Weight > v->Dist && u->Dist + e->Weight < v->Dist2) v->Dist2=u->Dist+e->Weight;
由u的次短路经放松:
if(u->Dist2 + e->Weight > v->Dist && u->Dist2 + e->Weight < v->Dist2) v->Dist2=u->Dist2 + e->Weight;
完整代码:
#include <cstdio> #include <cstring> #include <cassert> #include <queue> using namespace std; #define LOOP(i,n) for(int i=1; i<=n; i++) const int MAX_NODE = 5010, MAX_EDGE = 100010 * 2, INF = 0x3f3f3f3f; struct Node; struct Edge; struct Node { int Id, Dist, Dist2; bool Inq; Edge *Head; }_nodes[MAX_NODE], *Start, *Target; int _vCount; struct Edge { int Weight; Node *From, *To; Edge *Next; Edge() {} Edge(Node *from, Node *to, Edge *next, int weight) : From(from), To(to), Next(next), Weight(weight){} }*_edges[MAX_EDGE]; int _eCount; void Init(int vCount) { memset(_nodes, 0, sizeof(_nodes)); _vCount = vCount; _eCount = 0; Start = 1 + _nodes; Target = vCount + _nodes; } void AddEdge(Node *from, Node *to, int weight) { Edge *e = _edges[++_eCount] = new Edge(from, to, from->Head, weight); e->From->Head = e; } void Build(int uId, int vId, int weight) { Node *u = uId + _nodes, *v = vId + _nodes; u->Id = uId; v->Id = vId; AddEdge(u, v, weight); AddEdge(v, u, weight); } void SPFA() { LOOP(i, _vCount) _nodes[i].Dist = _nodes[i].Dist2 = INF; static queue<Node*> q; Start->Dist = 0; Start->Dist2 = INF; Start->Inq = true; q.push(Start); while (!q.empty()) { Node *u = q.front(); q.pop(); u->Inq = false; for (Edge *e = u->Head; e; e = e->Next) { bool relaxOk = false; if (u->Dist + e->Weight < e->To->Dist) { e->To->Dist2 = e->To->Dist; e->To->Dist = u->Dist + e->Weight; relaxOk = true; } else if (u->Dist + e->Weight > e->To->Dist && u->Dist + e->Weight < e->To->Dist2) { e->To->Dist2 = u->Dist + e->Weight; relaxOk = true; } if (u->Dist2 + e->Weight < e->To->Dist2) { e->To->Dist2 = u->Dist2 + e->Weight; relaxOk = true; } if (relaxOk && !e->To->Inq) { e->To->Inq = true; q.push(e->To); } } } } int main() { #ifdef _DEBUG freopen("c:\\noi\\source\\input.txt", "r", stdin); #endif int testCase, totNode, totEdge, uId, vId, weight, sId, tId; scanf("%d%d", &totNode, &totEdge); Init(totNode); LOOP(i, totEdge) { scanf("%d%d%d", &uId, &vId, &weight); Build(uId, vId, weight); } SPFA(); printf("%d\n", Target->Dist2); return 0; }