2012 ACM/ICPC Asia Regional Tianjin Online Travel
http://acm.hdu.edu.cn/showproblem.php?pid=4284
思路:预处理15个点之间的最短距离后暴力。

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> using namespace std; const int maxn = 105; const int inf = 1<<29; int dis[maxn][maxn]; int h[maxn],d[maxn],c[maxn],vis[maxn]; int N,M,H,tot,ok; void floyd() { int i,j,k; for( k=0; k<=N; k++ ) for( i=0; i<=N; i++ )if( k!=i ) for( j=0; j<=N; j++ )if(j!=i&&j!=k){ if( dis[i][j]>dis[i][k]+dis[k][j] ) dis[i][j]=dis[i][k]+dis[k][j]; } } void dfs(int x,int res,int cnt) { int i; if(cnt==H){ if(res>=dis[x][1])ok=1; return; } if(ok)return ; vis[x]=1; for(i = 0; i < H; ++ i)if(!vis[h[i]]){ int cost = d[i] + dis[x][h[i]]; if(res>=cost) dfs(h[i],res-cost+c[i],cnt+1); } vis[x]=0; } int main() { int i,j,k,t; scanf("%d",&t); while(t--){ scanf("%d %d %d",&N,&M,&tot); for(i = 0 ; i <= N; ++ i) for(j = 0; j <= N; ++ j) if(i^j)dis[i][j]=inf; else dis[i][j] = 0; for(i = 0; i < M; ++ i){ int u,v,w; scanf("%d %d %d",&u,&v,&w); if(dis[u][v]>w)dis[u][v]=dis[v][u]=w; } dis[0][1] = dis[1][0] = 0; scanf("%d",&H); for(i = 0; i < H; ++ i) scanf("%d %d %d",h+i,c+i,d+i); floyd(); ok = 0; memset(vis,0,sizeof(vis)); dfs(0,tot,0); if(ok)puts("YES"); else puts("NO"); } return 0; }