[回憶殺] 圖論進階(圖論初步被我喫,反正沒人看)(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 所以 對它改進也沒有意義(這一題 估計就是給新手練習的)。

(我去找一個 有必要 改進隊列實現的題目來,待續)

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

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