[回忆杀] 图论进阶(图论初步被我吃,反正没人看)(poj 1052)

(说实话,今天实验室的人去听宣讲会不和我说。之前问也不说在干什么,我很生气。不过算他们错过了一个‘人才’吧)


dijkstra算法概论:该算法应用在图论里面著名的 单源最短路径问题。


算法适用性:圣经 黑书指出,该算法应用在  无负权,有向图中。


算法复杂度:事实上,黑书是在图割、轻边的概念上展开算法。黑书维护了一个最小优先队列(以到d值排序),作为 V - S。 初始化后,每一次迭代(v 次)都对队列值最小的节点 的每一条出边进行松弛操作。因此维护队列 涉及到 插入(初始化),弹出(最小值),以及重排序(松弛操作)。前两者对于每一个节点都是一次操作,而重排序(堆的下沉操作)对每一个节点的每一条出边都要进行操作,所以是e次重排序。

若 按照 白书的代码 来实现(简单的数组操作,而不是最小二叉堆),则需要 V^2+E的复杂度。

仍然可以改进。加上稀疏图和最小二叉堆实现可以降低到,V^2/lgV.。

如果采用非波那契堆来实现,则可以降低到,VlgV+E。

(先回忆到这里,待续)(Linux下的编辑真是难看,我们继续)

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

刚刚出去找到了 POJ 1052,这个题目 直接是DAG单源最短路径问题,而且用最慢的Dj实现也通过了。代码如下,

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define INF 0xfffffff
#define MAXN 105

int d[MAXN];
int w[MAXN][MAXN];
int v[MAXN];
int n;

void dj(int s){
	memset(v, 0, sizeof(v));
	for(int i = 0; i < n; i++)
		d[i] = ( i == s ? 0 : INF );
	for(int i = 0; i < n; i++){
		int x, m = INF;
		for(int y = 0; y < n; y++)
			if( !v[y] && d[y] <= m )
				m = d[x=y];
		v[x] = 1;
		for(int y = 0; y < n; y++)
			if( w[x][y] != -1 && d[y] > d[x] + w[x][y])
				d[y] = d[x] + w[x][y];
	}
}

int s2i(char* str){
	if (str[0] == 'x') return -1;
	int ret = 0;
	while (*str)
		ret = ret * 10 + (*str++) - '0';
	return ret;
}

int main(){
	scanf("%d", &n);
	for(int i = 0; i < n; i++)
		for(int j = 0; j < n; j++)
			w[i][j] = -1;
	char input[40];
	for(int i = 0; i < n; i++){
		w[i][i] = 0;
		for(int j = 0; j < i; j++){
			scanf("%s", input);
			w[i][j] = w[j][i] = s2i(input);
		}
	}

	dj(0);

	int output = -1;
	for(int i = 1; i < n; i++)
		if( d[i] > output ) output = d[i];
	printf("%d\n", output);
	return 0;
}
关键算法在 dj 函数,采用数组实现最小优先队列(直接暴力遍历数组)找出最近的节点(轻边)。然后对 该节点所有 出边 进行松弛操作。
每一次找到的(最近节点)都要出列,这里通过访问标签来实现。事实上,在松弛操作的时候也可以维护祖先节点,进而在最后得到路径上的节点序列。

POJ 评判的耗时是0ms 所以 对它改进也没有意义(这一题 估计就是给新手练习的)。

(我去找一个 有必要 改进队列实现的题目来,待续)

--------------------------------------------------------------------------------------------------------------------------------------------------------------

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