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