1. 程式人生 > >P1875 佳佳的魔法藥水

P1875 佳佳的魔法藥水

空行 style right () 以及 現在 有一個 can else

P1875 佳佳的魔法藥水

題目描述

發完了 k 張照片,佳佳卻得到了一個壞消息:他的 MM 得病了!佳佳和大家一樣焦急 萬分!治好 MM 的病只有一種辦法,那就是傳說中的 0 號藥水 ……怎麽樣才能得到 0 號藥 水呢?你要知道佳佳的家境也不是很好,成本得足夠低才行……

題目描述:

得到一種藥水有兩種方法:可以按照魔法書上的指導自己配置,也可以到魔法商店裏去

買——那裏對於每種藥水都有供應,雖然有可能價格很貴。在魔法書上有很多這樣的記載:

1 份 A 藥水混合 1 份 B 藥水就可以得到 1 份 C 藥水。(至於為什麽 1+1=1,因為……這是魔

法世界)好了,現在你知道了需要得到某種藥水,還知道所有可能涉及到的藥水的價格以及

魔法書上所有的配置方法,現在要問的就是:1.最少花多少錢可以配制成功這種珍貴的藥水;

2.共有多少種不同的花費最少的方案(兩種可行的配置方案如果有任何一個步驟不同則視為 不同的)。假定初始時你手中並沒有任何可以用的藥水。

輸入輸出格式

輸入格式:

第一行有一個整數 N,表示一共涉及到的藥水總數。藥水從 0~N­1 順序編號,0 號藥水就是 最終要配制的藥水。

第二行有 N 個整數,分別表示從 0~N­1 順序編號的所有藥水在魔法商店的價格(都表示 1 份的價格)。

第三行開始,每行有 3 個整數 A、B、C,表示 1 份 A 藥水混合 1 份 B 藥水就可以得到 1 份 C 藥水。註意,某兩種特定的藥水搭配如果能配成新藥水的話,那麽結果是唯一的。也就是 說不會出現某兩行的 A、B 相同但 C 不同的情況。

輸入以一個空行結束。

輸出格式:

輸出兩個用空格隔開的整數,分別表示得到 0 號藥水的最小花費以及花費最少的方案的個

數。

輸入輸出樣例

輸入樣例#1:
7 
10 5 6 3 2 2 3 
1 2 0 
4 5 1 
3 6 2
輸出樣例#1:
10 3

說明

樣例說明:

最優方案有 3 種,分別是:直接買 0 號藥水;買 4 號藥水、5 號藥水配制成 1 號藥水,直接 買 2 號藥水,然後配制成 0 號藥水;買 4 號藥水、5 號藥水配制成 1 號藥水,買 3 號藥水、6 號藥水配制成 2,然後配制成 0。

 1 #include<cstdio>
 2
#define MAXN 1010 3 4 int mp[MAXN][MAXN],dis[MAXN],ans[MAXN]; 5 bool vis[MAXN]; 6 int n; 7 8 void dijstra() 9 { 10 11 for (int i=1; i<=n; ++i) 12 { 13 int mx = 1e9,u; 14 for (int j=1; j<=n; ++j) 15 if (mx>dis[j]&&!vis[j]) 16 { 17 mx = dis[j]; 18 u = j; 19 } 20 if (mx==1e9) break; 21 vis[u] = true; 22 for (int v=1; v<=n; ++v) 23 { 24 if (!mp[u][v]||!vis[v]) continue ; 25 if (dis[mp[u][v]]>dis[u]+mx) 26 { 27 dis[mp[u][v]] = dis[v]+mx; 28 ans[mp[u][v]] = ans[v]*ans[u]; 29 } 30 else if (dis[mp[u][v]]==dis[v]+mx) 31 ans[mp[u][v]] += ans[u]*ans[v]; 32 } 33 34 } 35 } 36 int main() 37 { 38 scanf("%d",&n); 39 for (int i=1; i<=n; ++i) 40 scanf("%d",&dis[i]),ans[i] = 1; 41 42 int a,b,c; 43 while (scanf("%d%d%d",&a,&b,&c)!=EOF) 44 { 45 mp[a+1][b+1] = c+1; 46 mp[b+1][a+1] = c+1; 47 } 48 dijstra(); 49 printf("%d %d",dis[1],ans[1]); 50 return 0; 51 }

P1875 佳佳的魔法藥水