Dijkstra[2つの隣接テーブル+優先キュー最適化]
4602 ワード
Dijkstaアルゴリズムでは,隣接行列を用いて保存する場合,第1点の無駄な空間が多く,第2点はアルゴリズムの時間的複雑度がO(n*n)であることを知っているが,このようなアルゴリズムはあまりよくないと言えるので,まず記憶構造を最適化し,隣接テーブルを用いて記憶することができ,次に優先キューでサイズをソートすることができることを考慮した.その時間的複雑さは大幅に低下した.
注意すべきはpairが最初の要素の大きさでソートされ、同じ場合には2番目にソートされるので、d[i]を最初の要素に包装します.
vectorは隣接テーブル+優先キューを実現する(エッジが最初は文字型であると仮定し、難易度を上げるためであると仮定する)
1
6 9
D E 13
B C 9
A B 1
A C 12
B D 3
E C 5
D C 4
D F 15
E F 4
A F
出力データ:
17
0 1 8 4 13 17
配列実装隣接テーブル+優先キュー
テストデータ:
1
6 9
1 2 1
1 3 12
2 3 9
2 4 3
5 3 5
4 3 4
4 5 13
4 6 15
5 6 4
1 6
出力:
17
0 1 8 4 13 17
注意すべきはpairが最初の要素の大きさでソートされ、同じ場合には2番目にソートされるので、d[i]を最初の要素に包装します.
vectorは隣接テーブル+優先キューを実現する(エッジが最初は文字型であると仮定し、難易度を上げるためであると仮定する)
#include
#include
#include
#include
入力データ:1
6 9
D E 13
B C 9
A B 1
A C 12
B D 3
E C 5
D C 4
D F 15
E F 4
A F
出力データ:
17
0 1 8 4 13 17
配列実装隣接テーブル+優先キュー
#include
#include
#include
#include
#define inf 0x7fffffff
using namespace std;
const int MAXN = 205;
int dis[MAXN];
int u[MAXN],v[MAXN],w[MAXN];
int first[MAXN],next[MAXN];
int n,m;
int src,ed;
typedef pair pii;
void init()
{
scanf("%d%d",&n,&m);
memset(first,-1,sizeof(first));
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u[i],&v[i],&w[i]);
next[i]=first[u[i]];
first[u[i] ]=i;
u[i+m]=v[i],v[i+m]=u[i],w[i+m]=w[i]; // ,
next[i+m]=first[u[i+m] ];
first[u[i+m] ]=i+m;
}
cin>>src>>ed;
for(int i=1;i<=n;i++) dis[i]= (i==src? 0:inf);// dis[i] , 。
}
void dijkstra()
{
priority_queue,greater >que;
que.push(pii(0,src));
while(!que.empty()){
pii tmp=que.top();
que.pop();
int x = tmp.second;
if(tmp.first!=dis[x]) continue; // , dis, dis , ,
for(int e=first[x];e!=-1;e=next[e]){ //
if(dis[v[e]]>dis[x]+w[e]){
dis[v[e] ]=dis[x]+w[e];
que.push(pii(dis[v[e] ],v[e]));
}
}
}
}
int main()
{
// freopen("1.in","r",stdin);
int _;
scanf("%d",&_);
while(_--){
init();
dijkstra();
if(dis[ed]==inf) cout<
テストデータ:
1
6 9
1 2 1
1 3 12
2 3 9
2 4 3
5 3 5
4 3 4
4 5 13
4 6 15
5 6 4
1 6
出力:
17
0 1 8 4 13 17