pku 3268(SPFA)

View Code
/*

  Name: bellmanFord算法的改进-->SPFA算法 

  Copyright: 

  Author: 

  Date: 18/04/12 22:29

  Description: 从x点正向求最短路及反向求最短路,累加最短时间,取最短时间的最大者 

*/



#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <iostream>



using namespace std;



const int N = 1005;

const int M = 100000;

const int MAX = 100000000;



bool vis[N];//判断顶点是否在队列中 

int dis[N], ans[N], Q[M], maxt;

struct edge {

    int v;

    int w;

    edge *next;

    edge(int vv, int ww, edge *p) {

        v = vv;

        w = ww;

        next = p;

    }

};

struct graph {

    edge *link;

}G[N], RG[N];//正向图,反向图 



void init(int n) {

    for (int i=0; i<n; ++i) G[i].link = RG[i].link = NULL;

    return ;

}



void buildG(int u, int v, int w) {//建图 

    edge *p = new edge(v, w, G[u].link);

    G[u].link = p;

    edge *q = new edge(u, w, RG[v].link);

    RG[v].link = q;

    return ;

}



/*

void del(edge *p) {

    if (!p) return ;

    del(p->next);

    delete p;

    return ;

}

*/    



void SPFA(int n, int s, int dir) {

    edge *p;

    int front, rear;

    for (int i=1; i<=n; ++i) dis[i] = MAX, vis[i] = false;

    front = rear = 0;

    Q[rear++] =  s;//源点入队列 

    dis[s] = 0;

    while (front < rear) {

        int u = Q[front++];

        vis[u] = false; //出队列改变标志 

        if (!dir) p = G[u].link;

        else p = RG[u].link;

        while (p) {

            if (dis[p->v] > dis[u] + p->w) {//松弛操作 

                dis[p->v] = dis[u] + p->w;

                if (!vis[p->v]) { //点不在队列里 

                    Q[rear++] = p->v;//入队列 

                    vis[p->v] = true;//标志 

                }

            }

            p = p->next;

        }

    }

    return ;

}



int main() {

    int n, m, x;

    while (scanf("%d%d%d", &n, &m, &x) != EOF) {

        init(n);

        int u, v, w;

        for (int i=0; i<m; ++i) {

            scanf ("%d%d%d", &u, &v, &w);

            buildG(u, v, w);

        }

        memset(ans, 0, sizeof(ans));

        maxt = 0;

        SPFA(n, x, 0);//正向求最短路 

        for (int i=1; i<=n; ++i) {

            if (i != x) ans[i] += dis[i];

        }

        SPFA(n, x, 1);//反向求最短路,并累加最短时间 

        for (int i=1; i<=n; ++i) {

            if (i != x) {

                ans[i] += dis[i];

                if (ans[i] > maxt) maxt = ans[i];//求最短时间的最大值 

            }

        }

        printf ("%d\n", maxt);

//        for (int i=1; i<=n; ++i) del(G[i].link), del(RG[i].link);

        edge *p;

        for (int i=1; i<=n; ++i) {

            p = G[i].link;

            while (G[i].link) {

                G[i].link = p->next;

                delete p;

                p = G[i].link;

            }

        }

        for (int i=1; i<=n; ++i) {

            p = RG[i].link;

            while (RG[i].link) {

                RG[i].link = p->next;

                delete p;

                p = RG[i].link;

            }

        }

    }

    return 0;

}

 

你可能感兴趣的:(SPFA)