题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4571
题目大意:小A去小B家,图中有多个点,每个点有一个两个值c,w,表示拜访该点消费的时间为c,同时获得的幸福指数为w,问你在时间T范围内,要求走走最短的路程,并且如果先拜访u再拜访v,那么v点的幸福指数大于u才可以去拜访,求小A能够获得的最大的幸福指数是多少。
解题思路:这题巨坑,开始用优先队列+bfs,无奈的TLE,后来又改成spfa,WA到死。
本题要求路程最短,可以先用floyd预处理出最短路,然后再在这个最短路的基础上进行spfa,spfa过程中每个点都有T个状态,dis[x][t]表示在时间t时刻x点获得的最大幸福指数是多少。思路是没错的,可怜的我WA的蛋疼了。最后发现从起点和终点这两个点是两个超级大bug,为什么这么说呢,你看假若直接从起点出发那么处理的必不是拜访起点,而你处理起点下一个点的时候表示的又是拜访了起点,这样是错的。对于终点,不是一定到要拜访终点,也可以只需到达即可。这两个bug太让人伤心了。怎么处理呢?建立两个虚拟节点(一个超级起点,一个超级终点),则两个起点的作用分别是拜访和不拜访,两个终点的作用也是如此。如果考虑到了这两点,基本问题就出来了。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <queue> 5 #include <cstring> 6 using namespace std; 7 8 const int maxn=110; 9 const int oo=0x3fffffff; 10 int S[maxn], C[maxn]; 11 int mp[maxn], visit[maxn][3*maxn]; 12 int map[maxn][maxn], cap[maxn][maxn], dis[maxn][3*maxn]; 13 int n, m, V, T, st, sd, ss, dd; 14 15 struct node 16 { 17 int u, t; 18 }; 19 20 void floyd() 21 { 22 ss=n, dd=n+1, S[dd]=0; 23 for(int k=0; k<n; k++) 24 for(int i=0; i<n; i++) 25 for(int j=0; j<n; j++) 26 if(map[i][j]>map[i][k]+map[k][j]) map[i][j]=map[i][k]+map[k][j]; 27 28 for(int i=0; i<n; i++) 29 for(int j=i+1; j<n; j++) 30 { 31 if(map[i][j]!=oo) 32 { 33 if(S[i]<S[j]) cap[i][j]=map[i][j]+C[j]; 34 if(S[j]<S[i]) cap[j][i]=map[i][j]+C[i]; 35 } 36 } 37 cap[ss][st]=C[st]; 38 for(int i=0; i<n; i++) 39 if(i!=st&&map[st][i]!=oo) cap[ss][i]=map[st][i]+C[i]; 40 for(int i=0; i<n; i++) 41 if(i!=sd&&map[i][sd]!=oo) cap[i][dd]=map[i][sd]; 42 43 } 44 45 46 int spfa() 47 { 48 queue<node>q; 49 for(int i=0; i<=n+1; i++) 50 for(int j=0; j<=V; j++) dis[i][j]=-oo, visit[i][j]=0; 51 node s, p; 52 s.u=ss, s.t=0; 53 q.push(s); 54 dis[ss][0]=0; 55 visit[ss][0]=1; 56 while(!q.empty()) 57 { 58 p=q.front(); 59 q.pop(); 60 visit[p.u][p.t]=0; 61 for(int i=0; i<=n+1; i++) 62 { 63 if(p.u!=i&&cap[p.u][i]!=oo) 64 { 65 int tp=p.t+cap[p.u][i]; 66 if(tp<=V&&dis[i][tp]<dis[p.u][p.t]+S[i]) 67 { 68 dis[i][tp]=dis[p.u][p.t]+S[i]; 69 s.u=i, s.t=tp; 70 if(!visit[s.u][s.t]) visit[s.u][s.t]=1,q.push(s); 71 } 72 } 73 } 74 } 75 int maxx=0; 76 for(int i=0; i<=V; i++) 77 { 78 maxx=max(maxx,dis[sd][i]); 79 maxx=max(maxx,dis[dd][i]); 80 } 81 return maxx; 82 } 83 84 int main() 85 { 86 cin >> T; 87 for(int tcase=1; tcase<=T; tcase++) 88 { 89 scanf("%d%d%d%d%d",&n,&m,&V,&st,&sd); 90 for(int i=0; i<=n+1; i++) 91 for(int j=0; j<=n+1; j++) 92 { 93 map[i][j]=oo, cap[i][j]=oo; 94 if(i==j) map[i][j]=cap[i][j]=0; 95 } 96 for(int i=0; i<n; i++) scanf("%d",C+i); 97 for(int i=0; i<n; i++) scanf("%d",S+i); 98 while(m--) 99 { 100 int u, v, val; 101 scanf("%d%d%d",&u,&v,&val); 102 map[u][v]=min(map[u][v],val); 103 map[v][u]=min(map[v][u],val); 104 } 105 floyd(); 106 int ans=spfa(); 107 printf("Case #%d:\n%d\n",tcase,ans); 108 } 109 return 0; 110 }