#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define x first
#define y second
using namespace std;
const int N = 25010,M=160010;
typedef pair<int, int> PII;
int n,P,R,S;
int dist[N],din[N],id[N];//id[i]表示i的所属集合的编号,din[i]表示id为i的点的集合的入度;
vector<int> block[N];//block[i]存储的是id为i的点的集合
int idcnt;//id的编号分配
queue<int> q;//入度为0的集合编号入队
bool st[N];//最短路判重
int h[N], e[M], w[M], ne[M], idx;
void add(int a, int b, int c) // 添加一条边a->b,边权为c
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
void dfs(int u,int idn)
{
id[u]=idn;
block[idn].push_back(u);
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(!id[j]) dfs(j,idn);
}
}
void dijkstra(int tid)
{
priority_queue<PII,vector<PII>,greater<PII>> heap;
for(int i=0;i<block[tid].size();i++)
heap.push({dist[block[tid][i]],block[tid][i]});
while(heap.size())
{
auto t=heap.top();
heap.pop();
int u=t.y;
if(st[u]) continue;
st[u]=true;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(id[j]!=id[u]&&--din[id[j]]==0) q.push(id[j]);
if(dist[j]>dist[u]+w[i])
{
dist[j]=dist[u]+w[i];
if(id[j]==id[u]) heap.push({dist[j],j});
}
}
}
}
void topsort()
{
memset(dist,0x3f,sizeof dist);
dist[S]=0;
for(int i=1;i<=idcnt;i++)
if(!din[i]) q.push(i);
while(q.size())
{
auto t=q.front();
q.pop();
dijkstra(t);
}
}
int main()
{
memset(h, -1, sizeof h);
cin>>n>>R>>P>>S;
for(int i=1;i<=R;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a, b, c),add(b,a,c);
}
for(int i=1;i<=n;i++)
if(!id[i]) dfs(i,++idcnt);//划分集合的过程
while(P--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a, b, c);
din[id[b]]++;//b所属的集合入度+1
}
topsort();//拓步排序求dijkstra
for(int i=1;i<=n;i++)
if(dist[i]>0x3f3f3f3f/2) printf("NO PATH\n");
else printf("%d\n",dist[i]);
return 0;
}