//Pro: 1003: [ZJOI2006]物流运输
//cost[i][j]表示第i天到第j天的最短路长度
//f[i]表示前i天的最小花费
//f[i]=min(f[j-1]+cost[j][i]*(i-j+1)+k) ,j<=i
//输出f[n]即为答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
inline int read()
{
char c=getchar();int num=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
num=num*10+c-'0';
return num;
}
const int N=105;
int n,m,k,e,d;
bool flag[N][N],vis[N];
int cost[N][N],f[N];
int head[N],num_edge;
struct Edge
{
int v,w,nxt;
}edge[N<<3];
inline void add_edge(int u,int v,int w)
{
edge[++num_edge].v=v;
edge[num_edge].w=w;
edge[num_edge].nxt=head[u];
head[u]=num_edge;
}
struct STA
{
int id,dis;
STA(int a=0,int b=0)
{
id=a,dis=b;
}
bool operator < (const STA &A) const
{
return dis>A.dis;
}
};
int dis[N];
priority_queue<STA> que;
int dijkstra()
{
memset(dis,0x3f,sizeof(dis));
dis[1]=0,que.push(STA(1,0));
int now;
while(!que.empty())
{
now=que.top().id,que.pop();
if(vis[now])
continue;
for(int i=head[now],v;i;i=edge[i].nxt)
{
v=edge[i].v;
if(vis[v])
continue;
if(dis[v]>dis[now]+edge[i].w)
{
dis[v]=dis[now]+edge[i].w;
que.push(STA(v,dis[v]));
}
}
}
return dis[m];
}
int main()
{
n=read(),m=read(),k=read(),e=read();
for(int i=1,a,b,c;i<=e;++i)
{
a=read(),b=read(),c=read();
add_edge(a,b,c);
add_edge(b,a,c);
}
d=read();
for(int i=1,x,a,b;i<=d;++i)
{
x=read(),a=read(),b=read();
for(int j=a;j<=b;++j)
flag[x][j]=1;
}
memset(cost,0x3f,sizeof(cost));
for(int i=1;i<=n;++i)
{
for(int j=i;j<=n;++j)
{
memset(vis,0,sizeof(vis));
for(int k=1;k<=m;++k)
{
for(int l=i;l<=j&&vis[k]==0;++l)
vis[k]|=flag[k][l];
}
cost[i][j]=dijkstra();
}
}
memset(f,0x3f,sizeof(f));
f[0]=-k;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=i;++j)
{
if(cost[j][i]==dis[0])
continue;
if(f[i]>f[j-1]+cost[j][i]*(i-j+1)+k)
f[i]=f[j-1]+cost[j][i]*(i-j+1)+k;
}
}
printf("%d",f[n]);
return 0;
}
//Pro: 1003: [ZJOI2006]物流运输
//cost[i][j]表示第i天到第j天的最短路长度
//f[i]表示前i天的最小花费
//f[i]=min(f[j-1]+cost[j][i]*(i-j+1)+k) ,j<=i
//输出f[n]即为答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
inline int read()
{
char c=getchar();int num=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
num=num*10+c-'0';
return num;
}
const int N=105;
int n,m,k,e,d;
bool flag[N][N],vis[N];
int cost[N][N],f[N];
int head[N],num_edge;
struct Edge
{
int v,w,nxt;
}edge[N<<3];
inline void add_edge(int u,int v,int w)
{
edge[++num_edge].v=v;
edge[num_edge].w=w;
edge[num_edge].nxt=head[u];
head[u]=num_edge;
}
struct STA
{
int id,dis;
STA(int a=0,int b=0)
{
id=a,dis=b;
}
bool operator < (const STA &A) const
{
return dis>A.dis;
}
};
int dis[N];
priority_queue<STA> que;
int dijkstra()
{
memset(dis,0x3f,sizeof(dis));
dis[1]=0,que.push(STA(1,0));
int now;
while(!que.empty())
{
now=que.top().id,que.pop();
if(vis[now])
continue;
for(int i=head[now],v;i;i=edge[i].nxt)
{
v=edge[i].v;
if(vis[v])
continue;
if(dis[v]>dis[now]+edge[i].w)
{
dis[v]=dis[now]+edge[i].w;
que.push(STA(v,dis[v]));
}
}
}
return dis[m];
}
int main()
{
n=read(),m=read(),k=read(),e=read();
for(int i=1,a,b,c;i<=e;++i)
{
a=read(),b=read(),c=read();
add_edge(a,b,c);
add_edge(b,a,c);
}
d=read();
for(int i=1,x,a,b;i<=d;++i)
{
x=read(),a=read(),b=read();
for(int j=a;j<=b;++j)
flag[x][j]=1;
}
memset(cost,0x3f,sizeof(cost));
for(int i=1;i<=n;++i)
{
for(int j=i;j<=n;++j)
{
memset(vis,0,sizeof(vis));
for(int k=1;k<=m;++k)
{
for(int l=i;l<=j&&vis[k]==0;++l)
vis[k]|=flag[k][l];
}
cost[i][j]=dijkstra();
}
}
memset(f,0x3f,sizeof(f));
f[0]=-k;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=i;++j)
{
if(cost[j][i]==dis[0])
continue;
if(f[i]>f[j-1]+cost[j][i]*(i-j+1)+k)
f[i]=f[j-1]+cost[j][i]*(i-j+1)+k;
}
}
printf("%d",f[n]);
return 0;
}