HDU-1874--ブロックされていないプロジェクトの続き-ダイクストラの最短経路

タイトル説明:

州は、長年にわたってブロック解除プロジェクト計画を実施した後、ようやく多くの道路を建設しました。ただし、道路を増やすのは良くありません。ある町から別の町に移動するたびに、選択できる道路計画がたくさんあり、計画によっては他の計画よりもはるかに短い距離になります。これは歩行者にとって非常に厄介です。
始点と終点がわかったので、始点から終点までの最短距離を計算してください。

入る:

この質問には複数のデータセットが含まれています。ファイルの最後まで処理してください。
データの各グループの最初の行には、2つの正の整数NとM(0 <N <200、0 <M <1000)が含まれています。これらは、それぞれ既存の町の数と建設された道路の数を表します。町には0からN-1までの番号が付けられています。
次はM線の道路情報です。各線には3つの整数A、B、X(0 <= A、B <N、A!= B、0 <X <10000)があり、町Aと町Bの間に長さXの双方向道路があることを示しています。 。
次の行には、開始点と終了点をそれぞれ表す2つの整数S、T(0 <= S、T <N)があります。

出力:

データのグループごとに、1行で移動する最短距離を出力してください。SからTへのルートがない場合は、-1を出力します。


アイデア:

明らかに、これは最短経路問題です。まず、最短経路を見つける方法を知る必要があります。最短経路を見つけるための3つのアルゴリズムを次に示します。この問題では、ダイクストラ最短経路アルゴリズムを使用します。

まずダイクストラのアルゴリズムの原理についてお話します。最短経路の長さが長い順に、ソースポイントから他のポイントへの最短経路が順番に取得されます。
簡単に言えば:

  1. 開始点sに最も近い点v1を見つけます。この点は、ソース点から直接離れている必要があります。
  2. 開始点からs倍短い最短経路を見つける:彼は、頂点に到達する前に、2つの状況しかありません。①ソースポイントから直接②ソースポイントからv1を経由します。
  3. 類推により、毎回最短点を見つける
  4. 最短点が見つかるたびに、始点とすべての点の間の距離を緩和する必要があります。つまり、この点を通過してから他の点に到達した場合、パスが短くなるかどうか
  5. 補助配列distを設定します。ここで、各コンポーネントdist [k]は、ソースポイントから残りの頂点kまで現在取得されている最短パスを表します。map[i] [j]は、頂点iから頂点jまでの最短パスを表します。
  6. 状態遷移方程式:uが今得られた最短経路ノードであると仮定します。dist[k]=min(dist[k],map[u][k]+dist[u]

グラフィカルな方法で最短経路を見つけるプロセスを見てみましょう。

ここに画像の説明を挿入


v0から残りのポイントへの最短経路を見つけます。

  1. v0からv1-v5までの距離は、順番に∞、10、∞、30、100です。
  2. v0に最も近い点はv2、距離は10で、緩和演算が実行されます。点v2の後、v0から他の点までの距離は∞、10、60、30、100になります。
  3. このとき、v0に最も近い点はv4(これまでに見つかった最短経路の点は緩和操作を行う必要がない)で、緩和操作を続けると、v0から各点までの距離は∞、10になります。 50、30、90
  4. など、最後のポイントまで。

次の表は、最短パスを見つけるシミュレーションです。

ここに画像の説明を挿入


コードは次のとおりです。

#include <iostream>
using namespace std;
#define inf 0x3f3f3f3f
#define M 201
int visit[M],map[M][M],dist[M];
int main()
{
    
    
	int n,m,a,b,dis,start,Min,next,targe;
	while(cin>>n>>m)
	{
    
    	
		for(int i=0;i<n;i++)
		{
    
    
			visit[i]=0;
			dist[i]=inf;
			for(int j=0;j<n;j++)
			{
    
    
				map[i][j]=inf;
			}
		}
		
		while(m--)
		{
    
    
			cin>>a>>b>>dis;
			map[a][b]=min(map[a][b],dis);
			map[b][a]=map[a][b]; 
		}
		
		cin>>start>>targe;
		dist[start]=0;
		visit[start]=1;//visit[i]=1表示点i已经是最短路径,不需要再进行松弛操作 
		while(start!=targe)
		{
    
    
			Min=inf;
			for(int i=0;i<n;i++)
			{
    
    
				if(map[start][i]!=inf)
					dist[i]=min(dist[i],map[start][i]+dist[start]);
				if(!visit[i]&&dist[i]<Min)
				{
    
    
					next=i;//寻找当前距离起点最近的点 
					Min=dist[i];
				}			
			}	
			if(Min==inf) break;
			start=next;//下一个开始的点就是当前距离起点最近的点 
			visit[start]=1;		
		}
		if(dist[targe]==inf) cout<<"-1"<<endl;
			else cout<<dist[targe]<<endl;	
	}	
	return 0;
}

おすすめ

転載: blog.csdn.net/weixin_45102820/article/details/114379538