分析可得 每种物品要么完全转换为另一种物品 要么保持不变 可以发现 最后总的价值就是 sgm(i:1->n) have[i]*value[j]*rate 其中have[i]是第i种物品初始数量 value[j]是第i种物品的最终去向j物品 rate是一路转换得到的转化率累乘之积
正向考虑无法建图 因为一个物品的数量可能会因为其他逻辑相邻(有转换关系)的物品的转化而多次增加 但是跑最短路时的松弛只能保留一个最优解 而无法累加
但是反向考虑 (具体建图见代码) 对于每一个物品 看其能否给它的逻辑相邻的物品一个更好的转换去向 这样就变成了一个最优解的问题 对于第i种物品 跑完最短路后我们就得到了 have[i]*value[j]*rate 中的后两项 再累加每一种物品即可
#include <bits/stdc++.h> using namespace std; struct node { int v; double w; int next; }; queue <int> que; node edge[100000]; double p[10010],h[10010],dis[10010],book[10010]; int first[10010]; int n,m,num; void addedge(int u,int v,double w) { edge[num].v=v; edge[num].w=w; edge[num].next=first[u]; first[u]=num++; return; } double spfa() { double w,res; int i,u,v; while(!que.empty()) que.pop(); for(i=1;i<=n+1;i++) { dis[i]=-1.0; book[i]=0; } que.push(n+1); dis[n+1]=0.0; book[n+1]=1; while(!que.empty()) { u=que.front(); que.pop(); book[u]=0; for(i=first[u];i!=-1;i=edge[i].next) { v=edge[i].v,w=edge[i].w; if(dis[v]<dis[u]+w) { dis[v]=dis[u]+w; if(!book[v]) { que.push(v); book[v]=1; } } } } res=0.0; for(i=1;i<=n;i++) { res+=pow(10.0,dis[i])*h[i]; } return res; } int main() { double w; int i,u,v,k; while(scanf("%d",&n)!=EOF) { if(n==0) break; for(i=1;i<=n;i++) { scanf("%lf%lf",&p[i],&h[i]); } memset(first,-1,sizeof(first)); num=0; for(i=1;i<=n;i++) { addedge(n+1,i,log10(p[i])); } scanf("%d",&m); while(m--) { scanf("%d%d",&k,&v); k--; while(k--) { scanf("%lf%d",&w,&u); addedge(u,v,log10(w)); v=u; } } printf("%.2f\n",spfa()); } return 0; }