HDU2544 最短路【Dijkstra算法詳解】

Dijkstra算法思想:Dijkstra算法採用的是一種貪心的策略,聲明一個數組dist來保存源點到各個頂點的最短距離和一個保存已經找到了最短路徑的頂點的集合:T。

1、初始時,原點 s 的路徑權重被賦爲 0 (dist[s] = 0)。若對於頂點 s 存在能直接到達的邊(s,m),則把dist[m]設爲w(s, m),同時把所有其他(s不能直接到達的)頂點的路徑長度設爲無窮大。此時,集合T只有頂點s。 

2、首先,從dist數組選擇最小值(即距離源點最小的點),則該值就是源點s到該值對應的頂點的最短路徑,並且把該點加入到T中,此時完成一個頂點的最短路徑的尋找。 

3、新加入的頂點是否可以到達其他頂點並且判斷通過該頂點到達其他點的路徑長度是否比源點直接到達短,如果是,就用源點到該點的距離+該點到其它點的距離替換在dist中的值。 

4、重複上述動作,直到T中包含了圖的所有頂點。

 

#include <iostream>
#include <cstring>
using namespace std;

int inf=99999999;
int n,m;
int p[1005][1005];
int dist[1005];         //源點到頂點i的最短距離
int path[1005];         //記錄最短路的路徑
int mark[1005];

void Dijkstra(int s)
{
	memset(mark,0,sizeof(mark));
	mark[s]=1;
	for(int i=1;i<=n;i++)//找到源點到另外n-1個點的最短路徑
	{
		dist[i]=p[s][i];
		path[i]=s;
	}
	int min;
	int u;
	for(int i=1;i<=n-1;i++)//控制循環,只需要循環n-1次即可 
	{
		min=inf;
		for(int j=1;j<=n;j++)
		{
			if(mark[j]==0&&dist[j]<min)//找到距源點最近的點
			{
				min=dist[j];
				u=j;
			}
		}
		mark[u]=1;//並標記 
		for(int j=1;j<=n;j++)//更新dist數組
		{
			if(mark[j]==0&&p[u][j]!=inf)//確保兩點之間有路 
			{
				if(dist[u]+p[u][j]<dist[j])
				{
					dist[j]=dist[u]+p[u][j];
					path[j]=u;
				}
			}
		}
		
	}
}

int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j) p[i][j]=0;
			else
			    p[i][j]=inf;
		}
	}
	int s;
	cin>>s;//輸入源點 
	for(int i=1;i<=n;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		p[a][b]=c;
		p[b][a]=c;
	}	
	Dijkstra(s);
	for(int i=1;i<=n;i++)
	{
		if(i!=s)
		{
			cout << "1" << "到" << i << "最短距離是:" << dist[i] << ",路徑是:" << i;
			int t=path[i];
			while(t!=s)
			{
				cout<<"--"<<t;
				t=path[t];
			}
			cout << "--" <<s<< endl;
		}
	}
	for(int i=1;i<=n;i++)
	{
		cout<<path[i]<<" ";
	}
	return 0;
}

 

可用優先級隊列進行優化,省去了每次都要從dist數組裏找最小值的過程。

問題鏈接:HDU2544 最短路

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
////////////////ac
struct node{
	int u;
	int cost;
	node(int vv=0,int cc=0)// u表示節點,cost表示出發點到u點的距離
	{
		u=vv;cost=cc;
	}
	friend bool operator<(node x,node y)
	{
		return x.cost>y.cost;	// 爲了使用Priority_queue隊列的小堆
	}
};
struct edge{
	int v;
	int w;
	edge(int vv=0,int ww=0)//// v表示邊的另一端節點即終點,w表示該邊的權重
	{
		v=vv;w=ww;
	}
};
vector<edge> v[105];
int dist[105]; // 出發點到某點的最短距離
int mark[105];
int inf=0x3f3f3f3f;
void dijkstra(int s,int n)
{
	// 用q來儲存下一步可能要取的節點的節點號和最小路徑長度(爲了排序)
	priority_queue<node> q;// 保存<u,dist[u]>且按dist[u]升序排列
	memset(mark,0,sizeof(mark));
	memset(dist,inf,sizeof(dist));
	dist[s]=0;
	q.push(node(s,0));
	node nn;
	while(!q.empty())
	{
		nn=q.top();
		q.pop();
		int u=nn.u;
		if(mark[u]==0)
		{
			mark[u]=1;
			int len=v[u].size();
			for(int i=0;i<len;i++)
			{
				int vv=v[u][i].v;
				if(mark[vv]==0)
				{
					int nextcost=dist[u]+v[u][i].w;
					if(dist[vv]>nextcost)
					{
						dist[vv]=nextcost;
						q.push(node(vv,dist[vv]));
					}
				}
			}
		}
	}
}
int main()
{
	int n,m;
	int a,b,c;
	while(cin>>n>>m&&!(n==0&&m==0))
	{
		for(int i=0;i<m;i++)
		{
			cin>>a>>b>>c;
			v[a].push_back(edge(b,c));
			v[b].push_back(edge(a,c));
		}
		dijkstra(1,n);
		cout<<dist[n]<<endl;
		for(int i=0;i<=n;i++)
		{
			v[i].clear();
		}

	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章