最短路



  算法訓練 最短路  
時間限制:1.0s   內存限制:256.0MB
      
問題描述
給定一個n個頂點,m條邊的有向圖(其中某些邊權可能爲負,但保證沒有負環)。請你計算從1號點到其他點的最短路(頂點從1到n編號)。
輸入格式
第一行兩個整數n, m。
接下來的m行,每行有三個整數u, v, l,表示u到v有一條長度爲l的邊。
輸出格式
共n-1行,第i行表示1號點到i+1號點的最短路。
樣例輸入
3 3
1 2 -1
2 3 -1
3 1 2
樣例輸出
-1
-2
數據規模與約定
對於10%的數據,n = 2,m = 2。
對於30%的數據,n <= 5,m <= 10。

對於100%的數據,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保證從任意頂點都能到達其他所有頂點。

SPFA算法:解決有向負權邊

  1. 算法大致流程是用一個隊列來進行維護。 初始時將源加入隊列。 每次從隊列中取出一個元素,
  2. 並對所有與他相鄰的點進行鬆弛,若某個相鄰的點鬆弛成功,則將其入隊。 直到隊列爲空時算法結束。
  3. 它可以在O(kE)的時間複雜度內求出源點到其他所有點的最短路徑,可以處理負邊。

queue:   q.front();

q.pop();

q.push();

#include<stdio.h>
#include<iostream>
using namespace std;
#define N 200001
#include<vector>
#include<queue>

typedef struct{
	int v;
	int w;
}node;
vector<node> g[N]; //一行最多有N這麼多的鄰接點
queue<node> q;
int inqueue[N], dist[N];

void spfa(){
	node e;
	int i, j, len;
	int start = 1;
	e.v = 1;
	e.w = 0;
	q.push(e);
	for(i = 0; i < N; i++){
		dist[i] = N;
	}
	dist[1] = 0;
	inqueue[1] = 1;
	while(!q.empty()){

		e = q.front();
		q.pop();
		int now = e.v;
		
		len = g[now].size();
		for(i = 0; i < len; i++){
			node next = g[now][i];
			if(next.v != 1 && (g[now][i].w + dist[now] < dist[next.v])){//不是源, 而且加上這條邊, 小於記錄的
				dist[next.v] = g[now][i].w + dist[now];
				if(inqueue[next.v] == 0){
					q.push(next);
					inqueue[next.v] = 1;
				}				
			}
		}
		inqueue[now] = 0;//出隊,標記爲不在隊中中
	}
}


int main(){
//	freopen("in.txt", "r", stdin);
	node e;
	int n, m;
	int u, v, l;
	scanf("%d%d", &n, &m);
	while(m--){
		scanf("%d%d%d", &u, &v, &l);
		e.v = v;
		e.w = l;
		g[u].push_back(e);//存儲有向圖		
	}
	spfa();	
	for(int i = 2; i <= n; i++){//明確用什麼參數記錄的點的數目
		printf("%d\n", dist[i]);
	}	
	return 0;
}


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