题解:
首先计算第一个答案,很明显就是最短路
初始代价是一开始配置的代价
当i+j配成k的时候,建i->k,j->k的边,价值为a[i]+a[j](a[i],a[j]都算过了)
那么计算第二个问题
当每一种药水的初始值没有变过的时候,合成方案位1,否则位0
然后看看哪两种药水可以合成位新的药水
dp记录
代码:
#include<bits/stdc++.h> using namespace std; const int N=1005; int n,a[N],b[N][N],f[N],x,y,z,sum[N]; int main() { // freopen("a.in","r",stdin); // freopen("a.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++)scanf("%d",&a[i]); while (~scanf("%d%d%d",&x,&y,&z))b[x+1][y+1]=b[y+1][x+1]=z+1; for (int i=1;i<=n;i++)sum[i]=1; for (int i=1;i<=n;i++) { int l=-1; for (int j=1;j<=n;j++) if (!f[j]&&(l==-1||a[l]>a[j]))l=j; f[l]=1; for (int j=1;j<=n;j++) if (b[l][j]&&a[b[l][j]]>a[l]+a[j]) a[b[l][j]]=a[l]+a[j],sum[b[l][j]]=0;; } memset(f,0,sizeof f); for (int i=1;i<=n;i++) { int l=-1; for (int j=1;j<=n;j++) if (!f[j]&&(l==-1||a[l]>a[j]))l=j; f[l]=1; for (int j=1;j<=n;j++) if (f[j]&&b[l][j]&&a[b[l][j]]==a[l]+a[j]) sum[b[l][j]]+=sum[l]*sum[j]; } printf("%d %d",a[1],sum[1]); }