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