本题为dp和最短路的结合,cost(X,Y) 表示从x到y时段的费用(注意最后时间是(Y-X+1), f [ i ] 表示到第i时段所需费用的最小值,dp方程:f[i]=min(f[i],f[j]+cost(j+1,i)+k) ;
/**************************************************************
Problem: 1003
User: EOD_realize
Language: C++
Result: Accepted
Time:40 ms
Memory:1480 kb
****************************************************************/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#define INF 0x3f3f3f3f
using namespace std;
int n,m,k,e,num;
const int maxn = 100 + 10;
const int maxm = maxn * maxn;
bool flag[maxn][maxn],done[maxn];
int dis[maxn],t[maxn],sum[maxn],f[maxn];
struct node
{
int v,dis;
node(int x,int y)
{
v=x;
dis=y;
}
};
int next[maxm],to[maxm],val[maxm],p[maxm];
void build(int x,int y,int w)
{
num++;
to[num]=y;
val[num]=w;
next[num]=p[x];
p[x]=num;
}
int cost(int s,int t)
{
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(done,false,sizeof(done));
for(int i=1;i<=m;i++)
{
for(int j=s;j<=t;j++)
{
if(!flag[i][j])
{
done[i]=1;
break;
}
}
}
queue<node>q;
int flag,minn;
dis[1]=0;
q.push(node(1,0));
while(!q.empty())
{
node now=q.front();
q.pop();
if(done[now.v]) continue;
for(int i=p[now.v];i;i=next[i])
{
if(done[to[i]]) continue;
if(dis[to[i]]>dis[now.v]+val[i])
{
dis[to[i]]=dis[now.v]+val[i];
q.push(node(to[i],dis[to[i]]));
}
}
}
if(dis[m]==INF) return INF;
else
return dis[m]*(t-s+1);
}
void readdata()
{
memset(flag,true,sizeof(flag));
scanf("%d%d%d%d",&n,&m,&k,&e);
for(int i = 1;i <= e;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
build(x,y,z);
build(y,x,z);
}
int d;
scanf("%d",&d);
for(int i = 1;i <= d;i++)
{
int p,a,b;
scanf("%d%d%d",&p,&a,&b);
for(int j = a;j <= b;j++)
flag[p][j] = false;
}
}
void solve()
{
for(int i=1;i<=n;i++)
{
f[i]=cost(1,i);
for(int j=2;j<i;j++)
{
f[i]=min(f[i],f[j]+k+cost(j+1,i));
}
}
printf("%d\n",f[n]);
}
int main()
{
readdata();
solve();
return 0;
}