ヒープアルゴリズムの最適化DIJ
アルゴリズムのDIJ時間の複雑さがある(O(N ^ 2)\ \) 、いくつかの問題では、明らかにこの複雑さの要件を満たしていないされています。だから我々はDIJ最適化アルゴリズム方法を模索し続ける必要があります。
最適化のヒープ原則
ヒープの最適化は、定義により、ヒープを最適化するために使用されます。私たちは、DIJ単純なアルゴリズムを学ぶ、アルゴリズムは、ポイントの上に最初から最後スイープにDIJを理解して、リラクゼーションの最小点を見つける必要があります。スキャン操作が簡単DIJ害犯人アルゴリズムの時間計算量です。だから我々は維持するために、プライオリティキューで、小さな根のヒープを使用する「最小点を。」大幅アルゴリズムDIJの時間複雑さを低減します。
ヒープ最適化されたコードの実装
言うは易し、行うは難たし。
我々は上記の一般的な考え方を理解した後は、このコードを書くために始めることができますが、我々は、コードは多くの詳細を扱っていないことがわかりました。
まず、プライオリティキュー最短長押しする必要がありますが、一度チームに、プライオリティキューが自動的に元の位置に残して、他の言葉で、私たちはそれを指すことはできません、それが元に対応して維持され、それはノーと言うことですポイント・マッピング・アプローチに右の点の数が形成されます。
私たちは、この問題を解決するためのペアを使用しています。
C ++は、タプルを運ぶの対です。我々は2つの要素の構造として、それを理解することができます。キーワードにして、キーワードとして第2の並べ替えキーに最初のキーワード:もっとエキサイティングなタプルはソートを構築しています。だから、我々は最初のビットの組との距離を保つため、第2のビット数を格納することができます。
その後、我々はどのように我々はそれの小さなヒープルートにそれを作るのですか、プライオリティキューは、実際に大規模な裸のルートヒープであることがわかりましたか?
2つの方法がありますが、最初のものは、最初の番号への鍵反対を取り、その後、反対の数を取るために時間を取ることです。第二は、プライオリティキューを再定義することです。
priority_queue<int,vector<int>,greater<int> >q;
これらの問題を解決するために、我々は喜んで書き留めし続け、その後、私たちは、リラクゼーションを書いたことがわかり、我々は明らかに緩和の新しい値も行くことにプライオリティキューに押し込まれたい、このような場合は、我々は問題が見つかりました:プライオリティキューがすでに同じタプル(すなわち、同じ2番目のキーワード)の数に存在する、我々はそれを削除する方法がありません、それを更新する方法はありません。ときに我々のキューとランニングので、いくつかのバグが存在します。
どのようにそれを行うには??
成功した優先度キューの要素が繰り返されることはありません維持し、そこに繰り返されるとヒープタプルの上、直接ポップアウトしている場合:私たちは、判決のサイクルに入るようになったとき。
だから我々は、スタック最適化されたコードを取得します:
priority_queue<pair<int,int> >q;
void dijkstra(int start)
{
memset(dist,0x3f,sizeof(dist));
memset(v,0,sizeof(v));
dist[start]=0;
q.push(make_pair(0,start));
while(!q.empty())
{
while(!q.empty() && (-q.top().first)>dist[q.top().second])
q.pop();
if(!q.empty())
return;
int x=q.top().second;
q.pop();
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(dist[y]>dist[x]+val[i])
{
dist[y]=dist[x]+val[i];
q.push(make_pair(-dist[y],y));
}
}
}
}