现在的位置: 首页 > 综合 > 正文

解题报告-HDOJ-1874(单源最短路径——Dijkstra)

2013年03月16日 ⁄ 综合 ⁄ 共 1794字 ⁄ 字号 评论关闭

Dijkstra算法

使用Dijkstra算法有前提条件,所有的边为正。

讲这个算法之前首先要先定义一个无穷大的量,用INF表示,而无穷大究竟是多大呢?我们知道在实际编程中,并不存在无穷大这个定义,每种数据类型都有其表示范围,而我们这里定义的无穷大,实际上是很大的整数,这个整数并不会影响到题目的其他数据。例如,题目中给定的数据为最大不超过100,而100000这个数相对于100已经很大了那么我们就可以定义无穷大INF = 100000。

定义一个dis数组,dis[i]表示i点到源点的最短距离。

定义一个used数组,用来标记点是否使用过。

 

算法思想:

初始化所有节点之间没有边,我们用无穷大来表示没有边。初始化dis数组为无穷大。初始化dis[star] = 0。

循环n次

{

         在所有未被标记的节点中找到dis值最小的节点x

         标记x节点

         从x节点出发,更新所有边(x,y),更新dis[y] = min{dis[y],  d[x] + map[x][y]}

}

例如,求0到5的最短距离:

初始化:

i

0

1

2

3

4

5

dis

0

INF

INF

INF

INF

INF

used

false

false

false

false

false

false

进行第一次的循环,找到了dis值最小的0节点,标记0节点,通过0节点去更新所有和0相关的节点得到:

i

0

1

2

3

4

5

dis

0

1

2

3

INF

10

used

true

false

false

false

false

false

进行第二次循环找到dis值最小的节点1,标记,通过1节点更新所有和1相关的节点得到:

i

0

1

2

3

4

5

dis

0

1

2

3

INF

10

used

true

true

false

false

false

false

如此类推:

第三次循环:

i

0

1

2

3

4

5

dis

0

1

2

3

INF

10

used

true

true

true

false

false

false

第四次循环:

dis[5] = min{dis[5],  d[3] + map[3][5]}

i

0

1

2

3

4

5

dis

0

1

2

3

INF

4

used

true

true

true

true

false

false

 

第五次循环:

i

0

1

2

3

4

5

dis

0

1

2

3

INF

4

used

True

true

true

true

false

true

第六次循环:

找不到了

结束循环,输出dis[5],即0到5点的最小距离为4。

1874-畅通工程续

实现代码:

#include <iostream>
using namespace std;

const int MAXN = 200 + 10;
int map[MAXN][MAXN];
int dis[MAXN];		//保存所有点到起点的最小距离
bool used[MAXN];
const INF = 0x3ffffff;

void init(int n)
{
	for (int i = 0; i < n; i++)
	{
		dis[i] = INF;
		for (int j = 0; j < n; j++)
		{
			map[i][j] = INF;
		}
	}
	memset (used,false,sizeof(used));
}

int dijkstra(int star, int end, int n)
{
	int MinNode;		//保存最小的距离
	dis[star] = 0;
	for (int i = 0; i < n; i++)		//贪心n次
	{
		int Min = INF;
		for (int j = 0; j < n; j++)
		{
			if (!used[j] && dis[j] < Min)
			{
				Min = dis[j];
				MinNode = j;
			}
		}
		used[MinNode] = true;
		//把MinNode作为中间点,进行松弛操作
		for (int k = 0; k < n; k++)
		{
			if (!used[k] && dis[k] > dis[MinNode] + map[MinNode][k])
			{
				dis[k] = dis[MinNode] + map[MinNode][k];
			}
		}
	}
	if (!used[end])
	{
		return -1;
	}
	else
	{
		return dis[end];
	}
}

int main()
{
	int n,m;
	while(cin>>n>>m)
	{
		int a,b,c;
		init(n);
		for (int i = 0; i < m; i++)
		{
			cin>>a>>b>>c;
			if(c < map[a][b])		//考虑如果有重边,用最小的进行构造图(好坑爹啊!!)
			{
				map[a][b] = c;
				map[b][a] = c;
			}
		}
		int s,t;
		cin>>s>>t;
		cout<<dijkstra(s, t, n)<<endl;
	}
	return 0;
}

 

抱歉!评论已关闭.