P1875 佳佳的魔法药水
题意:给出0~n-1号药水的价钱 我们要用最少的钱买0号药水;
题目中会给出某两种药水的融合品
让我们找出最少花的钱和方案数
思路:一开始做这道题的时候,想到的肯定就是最短路了,于是我朝着SPFA方面想
可是,我在建图方面并不知道怎么建。。。。想了大概一个小时也不知道如何建图
然后看了别人的题解,发现很多人都是用dij算法来做这道题
用这个算法来做这道题,倒是不用考虑建图方面的内容,可以直接算;
那么,到底怎么做呢?
题目中让我们求最短路径和方案数,我们分别用tmp1,tmp2这两个数组来表示
然后再用一个G【】【】来记录哪两种药水的融合品
然后就开始跑dij算法,跑松弛点的时候,跟模板是一样的
然后在松弛的时候,与模板略有不同
在模板中,是跑那些还没遍历的点,根据题目中给出的路径来松弛
而在本题中呢,是通过枚举已经松弛过的点,来松弛其他位置 (两者其实也差不多,hhhh)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e3+10; 4 const int inf=0x3f3f3f3f; 5 int tmp1[maxn]; 6 int tmp2[maxn]; 7 int G[maxn][maxn]; 8 int vis[maxn]; 9 int main() 10 { 11 int n; 12 scanf("%d",&n); 13 for(int i=0;i<n;i++){ 14 scanf("%d",&tmp1[i]); 15 tmp2[i]=1; 16 } 17 memset(G,-1,sizeof(G)); 18 int u,v,w; 19 while(scanf("%d%d%d",&u,&v,&w)!=EOF){ 20 // if(u==0) break; 21 G[u][v]=w; 22 G[v][u]=w; 23 } 24 for(int k=1;k<n;k++){ 25 int tmp=inf; 26 int base; 27 for(int j=0;j<n;j++){ 28 if(!vis[j]&&tmp>tmp1[j]){ 29 tmp=tmp1[j]; 30 base=j; 31 } 32 } 33 if(tmp==inf) break; 34 vis[base]=1; 35 for(int j=0;j<n;j++){ 36 if(vis[j]&&G[j][base]!=-1){ 37 if(tmp1[G[j][base]]>tmp1[j]+tmp1[base]){ 38 tmp1[G[j][base]]=tmp1[j]+tmp1[base]; 39 tmp2[G[j][base]]=tmp2[j]*tmp2[base]; 40 } 41 else if(tmp1[G[j][base]]==tmp1[j]+tmp1[base]){ 42 tmp2[G[j][base]]+=tmp2[j]*tmp2[base]; 43 } 44 } 45 } 46 } 47 printf("%d %d\n",tmp1[0],tmp2[0]); 48 return 0; 49 }