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;
}

 

posted on 2012-04-19 07:02  Try86  阅读(131)  评论(0)    收藏  举报