POJ 2449Remmarguts ' Date uvaoj 10740 not the best Dijkstra or SPFA or Bellman-ford k short circuit *

Source: Internet
Author: User
Tags bool min sort

First, the basic knowledge
Forward star and chain forward star representations of graphs (see here)
The forward star is a special array of edge sets, and we sort the starting point of each edge in the edge set array from small to large, and if the starting point is the same from small to large, and records the starting position and storage length of all the edges in the array starting with a point, the forward star is constructed. Use Len[i] and head[i] respectively to indicate the number and starting position of the edge with point I as the starting point. Because the forward star has a sort action, the quickest is the NLOGN level. But using a chain-forward star can avoid sorting.
You can set up the edge structure body:

struct Edge {
    int to, W, next;
} EDGE[M];

Where Edge[i].to is the end point of the section I, Edge[i].next represents the next storage position of the same edge as the beginning of the first edge, edge[i].w the weight of the edge.
Thus, a function that adds an edge can be written as:

void Addedge (int u, int v, int w)
{
    edge[ecnt].to = v;
    EDGE[ECNT].W = W;
    Edge[ecnt].next = Head[u];
    Head[u] = ecnt++;
}

Where ecnt is the number of edges, this function adds this edge to the beginning of the same edge as the previous starting point, and the head array is generally initialized to -1,ecnt initialized to 0. The order in which this is added and read is reversed, but does not affect the correctness of the result.

The examples below all use chain forward stars.
Two, the shortest path algorithm
The shortest path algorithm is generally divided into two steps of initialization and relaxation.
A. Dijkstra algorithm
Dijkstra is applicable to the case that the edge right is positive, in the case of negative side right, the shortest circuit can not be obtained correctly. The algorithm is applicable to both the forward graph and the non-direction graph. Below is the pseudo-code:

Clear all points of the label
set D[start] = 0, other d[i] = INF
loop n times {
    in all unlabeled nodes, select the node with the lowest D value x to the
    node x mark
    for all edges starting from X (x, y), update d[y] = Min (D[y], d[x] + w[x][y])
}

If you need to log the path, then add a pointer to the parent node of the array, each time the relaxation, update the parent node is OK.
The actual code is as follows:

void Dijkstra (int start)
{
    clr (vis, 0);
    for (int i = 1; I <= n; ++i) {
        dist[i] = INF;
    }
    Dist[start] = 0;
    for (int i = 1; I <= n; ++i) {
        int x = 0;
        int mnx = INF;
        for (int j = 1; j <= N; ++j) {
            if (!vis[j] && mnx >= dist[j]) {    //guaranteed to choose a point
                x = j;
                Mnx = Dist[j];
            }
        }
        Vis[x] = true;
        int p = rhead[x];
        while (P >= 0) {
            int v = redge[p].to;
            int w = redge[p].value;
            Dist[v] = min (dist[x] + W, dist[v]);
            p = Redge[p].next;}}}

The above code complexity is O (n^2), in the actual application can use the priority queue each time to select No Label D value of the smallest point, to relax, the complexity of O (Mlogn), each time out of the queue, if it has been marked, directly ignore the node is no longer expanded, the code is as follows:

void Heap_dijkstra (int start)
{
    clr (vis, 0);
    for (int i = 1; I <= n; ++i) {
        dist[i] = INF;
    }
    Dist[start] = 0;
    Priority_queue<node> PQ;
    Pq.push (Node (start, 0, 0));
    while (!pq.empty ()) {
        Node x = Pq.top ();
        Pq.pop ();
        if (vis[x.u]) {//slack over will no longer loosen
            continue;
        }
        VIS[X.U] = true;
        int p = rhead[x.u];
        while (P >= 0) {
            int a = Redge[p].from;
            int b = redge[p].to;
            int w = redge[p].value;
            if (Dist[b] > Dist[a] + W) {
                dist[b] = Dist[a] + W;
                Pq.push (Node (b, Dist[b], 0));
            }
            p = Redge[p].next;}}}

B. Bellman-ford algorithm
Dijkstra can not deal with a figure with negative rights, it is important to note that when the negative right exists, even the shortest path is not necessarily present, but there is a way to find it out in the case of minimum road existence. If the shortest path exists, there must be a short circuit that does not contain a ring. Since the loop is not included, the shortest path is only passed through the N-1 node (excluding the starting point), can be obtained by n-1 wheel relaxation operation. The code is as follows:

void Bellman_ford (int start)
{for
    (int i = 1; I <= n; ++i) {
        dist[i] = INF;
    }
    Dist[start] = 0;
    for (int i = 0; i < n-1; ++i) {//slack n-1 times
        for (int j = 0; j < m; ++j) {//per M edge slack
            int u = redge[j].from;
  
   int v = redge[j].to;
            if (Dist[u] < INF) {
                Dist[v] = min (Dist[v], Dist[u] + redge[j].value);}}}

  

It is shown that the complexity of the above algorithm is O (MN), SPFA (shortest Path Faster algorithm) algorithm can speak its optimization to O (KN), generally speaking k is less than or equal to 2.

Need to be aware that each time the queue to set the mark to true, when the team will be marked false, only update when the update, when not queued to join the queue, and record the number of times, if the number of times out of the team is equal to N (every time out of the team to relax with his connected points, then greater than n times the ring) Then there is a negative ring. The same Bellman-ford algorithm, if relaxed n-1 times, can also be relaxed, indicating a negative ring.

The following code exits when a negative loop is found, but only indicates that s can reach a negative ring and does not mean that the shortest path to each point is not present. In addition, if there is a negative ring in the diagram but s cannot reach the negative ring, then the above algorithm cannot be found. This can add a virtual point, the point to all the length of the point is 0, from this point to search once, you can find the picture is not a negative ring. This needs to be practiced in specific topics.

The code is as follows:

void spfa (int start) {for (int i = 1; I <= n; ++i) {dist[i] = INF;
    } Dist[start] = 0;
    CLR (c, 0);
    CLR (VIS, 0);
    Queue<int> Q;
    Q.push (start);
    Vis[start] = true;
        while (!q.empty ()) {int x = Q.front ();
        Q.pop ();
        int p = rhead[x];
        VIS[X] = false;;
            while (P >= 0) {int u = redge[p].from;
            int v = redge[p].to;
            int w = redge[p].value;
                if (Dist[u] + W < Dist[v]) {Dist[v] = Dist[u] + W;
                    if (!vis[v]) {Vis[v] = true;
                    ++C[V];
                    if (C[v] >= N) {return;
                } q.push (v);
        }} p = Redge[p].next; }
    }
}

Three, K short-circuit algorithm (see here)
Ask K short Circuit in fact the most easy to think of is the use of breadth-first search ideas, extension points, when this point k out of the queue, the current length of the found is the K short road, but this will produce more than the state, when the figure is relatively small, k value is smaller than the time can also be accepted.

At present, the use of more is single source shortest path with a * algorithm, where A * is used by the heuristic function h is the current node to the target node of the shortest, at this time, it is necessary to pre-reverse to find out from the target node to the other nodes shortest circuit length, the overall heuristic function f (u) =g (u) +h is the actual path length from the starting node to the current node, H (U) as described earlier.

Using a priority queue to process the node, first the starting node into the priority queue, from the priority queue to remove the minimum F-value of the node, if the target node so that the calculation has reached the number of times, if it is K, then exit, the current G value is the answer, otherwise, will be the current node as the starting point of the end of the It is important to note that when s is equal to T, the k+1 short circuit is required because the 1th short circuit is 0, which counts as no walk.

The code is as follows:

int BFs (void)
{
    priority_queue<node> pq;
    Pq.push (Node (s, 0, Dist[s]));
    if (dist[s] = = INF) {   //cannot reach
        return-1;
    }
    int cnt = 0;
    while (!pq.empty ()) {
        Node u = pq.top ();
        Pq.pop ();
        if (u.u = = t) {
            ++cnt;
        }
        if (u.u = = T && cnt = = k) {
            return u.g;
        }
        int p = head[u.u];
        while (P >= 0) {
            pq.push (Node (edge[p].to, U.G + Edge[p].value, dist[edge[p].to]));
            p = edge[p].next;
        }
    }
    return-1;
}

Below is the POJ 2449 and uvaoj10740 of the topic code, to find the shortest way to use a variety of methods, that is, bare to ask K short:

/************************************************************************* > File name:2449.cpp > Author:g Wq > Mail:gwq5210@qq.com > Created time:2015 August 28 Friday 09:53 34 seconds ************************************** /#include <cmath> #include <ctime> #include <cctype> #include <climits> #include <cstdio> #include <cstdlib> #include <cstring> #include <map> #include <set> #include <queue> #include <stack> #include <string> #include <vector> #include < sstream> #include <iostream> #include <algorithm> #define INF (INT_MAX/10) #define CLR (arr, Val) memset (
Arr, Val, sizeof (arr)) #define PB push_back #define SZ (a) ((int) (a). Size ()) using namespace Std;
typedef set<int> SI;
typedef vector<int> VI;
typedef map<int, Int> Mii;
typedef pair<int, int> PII;

typedef long Long LL;

Const double ESP = 1e-5; #define N 1010 #define M 100010 int n, m, S, T, K;
int Head[n], ecnt, Rhead[n], recnt, Dist[n], c[n];

BOOL Vis[n]; struct Edge {int from, to, value, next;}

EDGE[M], redge[m];
    struct Node {int u, g, H;

Node () {} node (int uu, int gg, int hh): U (UU), G (GG), H (HH) {}};

BOOL Operator < (node u, node v) {return u.g + u.h > v.g + v.h;}
    void Addedge (int u, int v, int x) {edge[ecnt].from = u;
    Edge[ecnt].to = v;
    Edge[ecnt].value = x;
    Edge[ecnt].next = Head[u];
Head[u] = ecnt++;
    } void Addredge (int u, int v, int x) {redge[recnt].from = u;
    Redge[recnt].to = v;
    Redge[recnt].value = x;
    Redge[recnt].next = Rhead[u];
Rhead[u] = recnt++;
    } void Dijkstra (int start) {clr (VIS, 0);
    for (int i = 1; I <= n; ++i) {dist[i] = INF;
    } Dist[start] = 0;
        for (int i = 1; I <= n; ++i) {int x = 0;
        int mnx = INF; for (int j = 1; j <= N; ++j) {if (!vis[j] && mnx >= Dist[j]) {//guaranteed to choose a point x = j;
            Mnx = Dist[j];
        }} Vis[x] = true;
        int p = rhead[x];
            while (P >= 0) {int v = redge[p].to;
            int w = redge[p].value;
            Dist[v] = min (dist[x] + W, dist[v]);
        p = redge[p].next;
    }}} void Heap_dijkstra (int start) {clr (VIS, 0);
    for (int i = 1; I <= n; ++i) {dist[i] = INF;
    } Dist[start] = 0;
    Priority_queue<node> PQ;
    Pq.push (Node (start, 0, 0));
        while (!pq.empty ()) {Node x = Pq.top ();
        Pq.pop ();
        if (Vis[x.u]) {continue;
        } vis[x.u] = true;
        int p = rhead[x.u];
            while (P >= 0) {int a = Redge[p].from;
            int b = redge[p].to;
            int w = redge[p].value;
                if (Dist[b] > Dist[a] + W) {dist[b] = Dist[a] + W;
    Pq.push (Node (b, Dist[b], 0));        } p = Redge[p].next;
    }}}} void Bellman_ford (int start) {for (int i = 1; I <= n; ++i) {dist[i] = INF;
    } Dist[start] = 0;
            for (int i = 0, i < n-1; ++i) {for (int j = 0; j < m; ++j) {int u = redge[j].from;
            int v = redge[j].to;
            if (Dist[u] < INF) {Dist[v] = min (Dist[v], Dist[u] + redge[j].value);
    }}}} void Spfa (int start) {for (int i = 1; I <= n; ++i) {dist[i] = INF;
    } Dist[start] = 0;
    CLR (c, 0);
    CLR (VIS, 0);
    Queue<int> Q;
    Q.push (start);
    Vis[start] = true;
        while (!q.empty ()) {int x = Q.front ();
        Q.pop ();
        int p = rhead[x];
        VIS[X] = false;;
            while (P >= 0) {int u = redge[p].from;
            int v = redge[p].to;
            int w = redge[p].value; if (Dist[u] + W < Dist[v]) {Dist[v] = dist[U] + w;
                    if (!vis[v]) {Vis[v] = true;
                    ++C[V];
                    if (C[v] >= N) {return;
                } q.push (v);
        }} p = Redge[p].next;
    }}} int bfs (void) {priority_queue<node> pq;
    Pq.push (Node (s, 0, Dist[s]));
    if (dist[s] = = INF) {//cannot reach return-1;
    } int cnt = 0;
        while (!pq.empty ()) {Node u = pq.top ();
        Pq.pop ();
        if (u.u = = t) {++cnt;
        } if (u.u = = T && cnt = = k) {return u.g;
        } int p = head[u.u];
            while (P >= 0) {Pq.push (Node (edge[p].to, U.G + Edge[p].value, dist[edge[p].to]));
        p = edge[p].next;
}} return-1;
        } int main (int argc, char *argv[]) {while (scanf ("%d%d", &n, &m)! = EOF) {int u, V, x;
CLR (head,-1);        CLR (Rhead,-1);
        ecnt = 0;
        recnt = 0;
            for (int i = 0; i < m; ++i) {scanf ("%d%d%d", &u, &v, &x);
            Addedge (U, v, x);
        Addredge (V, u, x);
        } scanf ("%d%d%d", &s, &t, &k);
        if (s = = t) {++k;
        }//dijkstra (t);
        Bellman_ford (t);
        SPFA (t);
        Heap_dijkstra (t);
    printf ("%d\n", BFS ());
} return 0; }

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.