题目大意:求图的严格次短路。

方法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;
}
View Code

相关文章: