分析可得 每种物品要么完全转换为另一种物品 要么保持不变 可以发现 最后总的价值就是 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;
}