单源最短路—dijkstra算法

dijkstra用于解决无负权的带权有向图或无向图的单源最短路径问题,时间复杂度为V^2,用对优化的时间复杂度为E*log(V)(优化常用稀疏图);dijkstra算法常用于一些问题的预处理上;

dijkstra算法是按照最短路距离源点由近及远的顺序逐一求出每个点距离源点的最短路的;用近点去更新,退出远点的距离,局部最优决定整体最优;

具体实现:贪心的思想,设s是源点,如果离s前k-1近的点已经被确定,构成点集P,那么从s到离s第k近的点t的路径{s,p1,p2,p3,......pi,t}满足s,p1,p2,p3......pi属于P;如果有pi不属于P的话,因为边权非负,pi到t的路径非负,则d[pi] <= d[t],pi才是第k近;

(1)、初始化d[i] = i == s ? 0 : INF; P为空集;

(2)、找到最小的d[i](i不属于P);

(3)、把i加入P中,对于任意的j不属于P,更新d[j]的值:d[j] = min(d[j],d[i] + dist[i][j]);

(4)、循环直到所有的点都加入集合P中;

poj3159  dijkstra模板题;

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<string>
#include<stack>
#include<map>
#define ll long long
#define MAX 50010
#define MAXN 150010
#define INF 2000000000
#define eps 1e-8

using namespace std;

struct Edge{
	int from,to,dist;
};

struct Node{
	int num,w;
	bool operator < (const Node& rhs) const{
		return rhs.w < w;
	}
};

vector<Edge>edges;
int first[MAXN],next[MAXN];  //刚开始用了一个vector<int>G[MAX]建图,发现会超时 

int n;

void init(){
	memset(first,-1,sizeof(first));
	memset(next,-1, sizeof(next));
	//for (int i=0; i<=n; i++) G[i].clear();
	edges.clear();
}

void addEdge(int from, int to, int dist){
	edges.push_back((Edge){from,to,dist});
	int k = edges.size();
	next[k-1] = first[from];
	first[from] = k-1;
}

int dijkstra(int s){
	int d[MAX],vis[MAX];
	priority_queue<Node>q;
	q.push((Node){s,0});
	memset(vis,0,sizeof(vis));
	for (int i=0; i<n; i++) d[i] = (i == s ? 0 : INF);
	while (!q.empty()){
		Node t = q.top();
		q.pop();
		int u = t.num;
		if (vis[u]) continue;
		vis[u] = 1; 
		for (int v=first[u]; v != -1; v = next[v]){
			Edge  e  = edges[v];
			if (!vis[e.to]){
				d[e.to] = min(d[e.to],d[u] + e.dist);
				q.push((Node){e.to,d[e.to]});
			}
		}
	}
	return d[n-1];
}

int main(){
	int m;
	while (scanf("%d%d",&n,&m) != EOF){
		int x,y,z;
		init();
		for (int i=0; i<m; i++){
			scanf("%d%d%d",&x,&y,&z);
			x--;
			y--;
			addEdge(x,y,z);
		}
		printf("%d\n",dijkstra(0));
	}
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值