package luogu;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
//描述
//N个农场各一头奶牛(1≤ N≤ 1000)方便编号的1..N将参加在农场#X举行的大型奶牛派对1≤ X≤ N) 。1≤ M≤ 100000)共M单向道路连接两个农场;道路i需要Ti(1≤ Ti≤ 100)穿越的时间单位。
//每头母牛都必须步行去参加聚会,聚会结束后,回到她的农场。每头母牛都很懒,因此可以用最短的时间选择最佳路线。一头母牛的返回路线可能与她最初到达派对的路线不同,因为道路是单向的。
//在所有的奶牛中,一头奶牛往返于派对的最长时间是多少?
//输入
//第1行:三个空格分隔的整数,分别为:N、M和X
//第2..M+1行:第i+1行用三个空格分隔的整数描述道路i:Ai、Bi和Ti。所述道路从农场Ai延伸至农场Bi,需要Ti时间单位来穿越。
//输出
//第1行:一个整数:任何一头牛必须行走的最长时间。
//题意:N头奶牛M条单向道路,到X举行派对,1,N头奶牛到X举行派对,每头母牛都很懒,因此可以用最短的时间选择最佳路线2,举行完派对,返回自己农场,求N头牛中,哪头牛花费最长的时间?
//题解:
//1.从N个农场到X农场求最短距离,即反向建边,求X到N个农场的最短距离
//2.从X农场返回各自农场最短距离,即正向求dijkstra
//最终1和2距离和最大的即是求花费时间最长的奶牛时间
//4 8 2
//1 2 4
//1 3 2
//1 4 7
//2 1 1
//2 3 5
//3 1 2
//3 4 4
//4 2 3
public class POJ3268 {
static int N,M,X;
static boolean visited[];
static int dis[];
static List<Node2> adjList[];
static int backDis[];
static int ans;
static boolean backVisited[];
static List<Node2> backList[];
public static void main(String[] args) throws Exception {
System.setIn(new FileInputStream("src/test/Solution.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while(br.ready()) {
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
X = Integer.parseInt(st.nextToken());
adjList = new List[N+1];
backVisited = new boolean[N+1];
visited = new boolean[N+1];
dis = new int[N+1];
backDis = new int[N+1];
backList = new List[N+1];
Arrays.fill(dis, Integer.MAX_VALUE/2);
Arrays.fill(backDis, Integer.MAX_VALUE/2);
Arrays.fill(visited, false);
Arrays.fill(backVisited, false);
for (int i = 1; i <= N; i++) {
adjList[i] = new ArrayList<Node2>();
backList[i] = new ArrayList<Node2>();
}
for (int i = 1; i <= M; i++) {
st = new StringTokenizer(br.readLine());
int s = Integer.parseInt(st.nextToken());
int e = Integer.parseInt(st.nextToken());
int len = Integer.parseInt(st.nextToken());
adjList[s].add(new Node2(e,len)); //求X农场奶牛到N个农场最短距离,即正向建边,求X到N个农场的最短距离
backList[e].add(new Node2(s,len));//原本求N个农场奶牛到X农场最短距离,即反向建边,求X到N个农场的最短距离
}
dijkstra();
dijkBackStra();
ans = 0;
int x = 0;
for (int i = 1; i <= N; i++) {
x=Math.max(dis[i]+backDis[i], x);//求花费时间最长的奶牛时间
}
ans = x;//任何一头牛必须行走的最长时间。
System.out.println(ans);
}
}
private static void dijkstra() {
PriorityQueue<Node2> pq = new PriorityQueue<Node2>(11,new Comparator<Node2>() {
@Override
public int compare(Node2 o1, Node2 o2) {
return o1.len-o2.len;
}
});
pq.add(new Node2(X,0));
dis[X]=0;
while(!pq.isEmpty()) {
Node2 curr = pq.poll();
if(!visited[curr.pos]) {
visited[curr.pos]=true;
for (int i = 0; i < adjList[curr.pos].size(); i++) {
Node2 next = adjList[curr.pos].get(i);
if(next.len+curr.len<dis[next.pos]) {
dis[next.pos]=next.len+curr.len;
pq.add(new Node2(next.pos,dis[next.pos]));
}
}
}
}
}
private static void dijkBackStra() {
PriorityQueue<Node2> pqBack = new PriorityQueue<Node2>(11,new Comparator<Node2>() {
@Override
public int compare(Node2 o1, Node2 o2) {
return o1.len-o2.len;
}
});
pqBack.add(new Node2(X,0));
backDis[X]=0;
while(!pqBack.isEmpty()) {
Node2 curr = pqBack.poll();
if(!backVisited[curr.pos]) {
backVisited[curr.pos]=true;
for (int i = 0; i < backList[curr.pos].size(); i++) {
Node2 next = backList[curr.pos].get(i);
if(next.len+curr.len<backDis[next.pos]) {
backDis[next.pos]=next.len+curr.len;
pqBack.add(new Node2(next.pos,backDis[next.pos]));
}
}
}
}
}
}
class Node2{
int pos;
int len;
public Node2(int pos,int len) {
this.pos = pos;
this.len=len;
}
}