比較的斬新なアイデアが、タイトルの思考を行うのはかなり良いです
あなたが見ると、ほとんどの短絡を考える。データの範囲を見ることを期待することができ、最小数は回数に記録しなければならない時間を実行しますDIJ。原因を記録する最短経路プログラムである薬剤は、より高価な構成を有している場合を証明するのは簡単です、我々これは、高価なの種類を記録しません。
そこで、我々は、dijの最適化されたヒープにこの質問を使用することができます。ヒープの最上部にあるポーションは、この薬は何も安く設定することができない場合
以前の方法よりも安価C AシロップシロップシロップBとの合成は構成で見つかった場合、シロップAシロップ設定量の設定方法C \(* \)構成Bシロップ。
構成溶液およびB溶液によって合成Cシロップは数設定Cシロップとして以前に見出され、構成Cシロップに等しい場合\(+ \)構成Aシロップ\(* \) Bシロップ設定。
グラフトラバーサル時には、2つだけは、シロップ最小コストであることが確認されており、それらの合成の薬は、彼らがこれらの2つの方法を証明するために得ることができる最小値は最小コストで次のようになります。彼らは、ヒープに表示された場合前に、それらは最小のコストでなければなりません。この操作は、アレイ気力を達成することができます
マップ全体を横断し、最終的に0から+ 0〜コンフィギュレーション手法は、回答番号です
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define pp pair<int,int>
#define f first
#define s second
const int MAXN = 1e3+5;
vector<pp> adj[MAXN];
priority_queue<pp> q;
int n;
int dist[MAXN], ways[MAXN],ans1,ans2,in[MAXN];
bool vis[MAXN];
int main(){
cin >> n;
for (int i=0;i<n;i++){
cin >> dist[i];
ways[i] = 1;//一开始都只有一种
q.push(make_pair(-dist[i],i));//扔进堆
}
ans1 = dist[0]; ans2 = 1;
int a,b,c;
while(cin >> a >> b >> c){
adj[a].push_back(make_pair(b,c));
if(a!=b)adj[b].push_back(make_pair(a,c));//注意,他可能出现A+A=C.这种情况不需要连两次边
}
while(!q.empty()){
int qf = -q.top().f, qs = q.top().s; q.pop();
if (dist[qs]!=qf) continue;//如果一个点的最小距离不等于在堆顶的距离,说明这个点已经更新过了,不需要再更新
vis[qs] = true;//这个点被拿过了
for (pp v : adj[qs]){
if (!vis[v.f]) continue;//如果另一种药水没被拿过,我们不能确定现在他的距离是最小的
if (dist[v.s]>qf+dist[v.f]){
dist[v.s] = qf+dist[v.f];
ways[v.s] = ways[v.f]*ways[qs];
q.push(make_pair(-dist[v.s],v.s));//刚刚讲过的转移
}else if (dist[v.s]==qf+dist[v.f]){
ways[v.s] += ways[v.f]*ways[qs];
}
}
}
cout << dist[0] << " " <<ways[0];//答案
}