HDU 3696 Farm Game
SPFA最长路,思路如下:
先对题目中给出的每条边建边,权值为转化率;增加一个终点S,每个节点到S建边,权值为该物品的单价。
假设X物品最终转化为了Y物品,那么转化之后得到的钱就是 W[x]*转化率1*转化率2*转化率3*转化率4*.....*P[Y]
现在我们关注 转化率1*转化率2*转化率3*转化率4*.....*P[Y] 这个式子,实际上就是求这个式子的最大值。
怎么求?事实上就是节点X到节点S的最长路。如果这样去求,那么需要N次SPFA;所以我们需要反向建边,从S出发开始求最长路。最终比较一下转换后的价格和之前的价格哪个大,就用哪个。.
描述的不够清楚的话,请看这篇博客:
http://blog.csdn.net/power721/article/details/6968014
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; const double INF=2100000000.0; struct Edge { int from,to; double cost; }e[50000+10]; int tot; vector<int>G[10000+10]; double price[10000+10],num[10000+10]; int N,M,K; int a[50000+10]; double b[50000+10]; int flag[10000+10]; double dis[10000+10]; void init() { for(int i=0;i<10000+10;i++) G[i].clear(); tot=0; } void spfa() { queue<int>Q; for(int i=0;i<=N;i++) dis[i]=-INF; memset(flag,0,sizeof flag); dis[0]=1; flag[0]=1; Q.push(0); while(!Q.empty()) { int h=Q.front();Q.pop();flag[h]=0; for(int i=0;i<G[h].size();i++) { int id=G[h][i]; if(dis[h]*e[id].cost>dis[e[id].to]) { dis[e[id].to]=dis[h]*e[id].cost; if(flag[e[id].to]==0) { flag[e[id].to]=1; Q.push(e[id].to); } } } } } int main() { while(~scanf("%d",&N)) { if(N==0) break; init(); for(int i=1;i<=N;i++) scanf("%lf%lf",&price[i],&num[i]); scanf("%d",&M); for(int i=1;i<=M;i++) { scanf("%d",&K); scanf("%d",&a[0]); for(int j=1;j<=K-1;j++) scanf("%lf%d",&b[j],&a[j]); for(int j=1;j<=K-1;j++) { e[tot].from=a[j]; e[tot].to=a[j-1]; e[tot].cost=b[j]; G[a[j]].push_back(tot); tot++; } } for(int i=1;i<=N;i++) { e[tot].from=0; e[tot].to=i; e[tot].cost=price[i]; G[0].push_back(tot); tot++; } spfa(); double ans=0; for(int i=1;i<=N;i++) ans=ans+num[i]*max(dis[i],price[i]); printf("%.2lf\n",ans); } return 0; }