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;
}

猜你喜欢

转载自blog.csdn.net/aaaaawyf/article/details/82594941
今日推荐