最短路



  算法训练 最短路  
时间限制: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;
}


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