//http://acm.hdu.edu.cn/showproblem.php?pid=4284
//先floyd,把h个点之间的最短路求出来,再就是直接对个h点爆搜,因为这里只要判断行不行,不行或行都会起到减枝作用,所以爆搜是难超时的;用h个点的终点记录状压dp应该是正解;
//下面是爆搜的代码:
#include<stdio.h> #include<string.h> #define inf 10000000 int map[110][110],h,vis[20]; struct node { int id,get,cot; }num[20]; int dfs(int dep,int rem,int root) { int i,tem; if(dep==h) return rem-map[root][1]>=0; for(i=1;i<=h;i++) { tem=rem-map[root][num[i].id]-num[i].cot; if(!vis[i]&&tem>=0) { vis[i]=1; if(dfs(dep+1,tem+num[i].get,num[i].id)) return 1; vis[i]=0; } } return 0; } int main() { int n,m,t,i,j,k,a,b,c,cas; scanf("%d",&cas); while(cas--) { scanf("%d%d%d",&n,&m,&t); for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=inf; for(i=1;i<=n;i++)map[i][i]=0; for(i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); if(map[a][b]>c) { map[a][b]=c; map[b][a]=c; } } for(i=1;i<=n;i++) for(j=1;j<=n;j++) for(k=1;k<=n;k++) if(map[j][i]+map[i][k]<map[j][k]) map[j][k]=map[j][i]+map[i][k]; scanf("%d",&h); for(i=1;i<=h;i++) { vis[i]=0; scanf("%d%d%d",&num[i].id,&num[i].get,&num[i].cot); } puts(dfs(0,t,1)?"YES":"NO"); } return 0; }