最短路——Dijkstra

最短路——Dijkstra

Dijkstra

是一种单源最短路径的算法,即找出起始点到其他所有点的最短路径。但是Dijkstra算法不能处理含有负边权的图。

算法描述

  1. 设置出发顶点为v,顶点集合V{v1,v2,vi…vn},v到V中各顶点的距离构成距离集合dis,dis{d1,d2,di…dn},Dis集合记录着v到图中各顶点的距离(到自身可以看作0,v到vi距离对应为di,初始时,设置di=oo)
  2. 从dis中选择值最小的di并移出dis集合,同时移出V集合中对应的顶点vi,此时的v到vi即为最短路径
  3. 更新dis集合,更新规则为:比较v到V集合中顶点的距离值,与v通过vi到V集合中顶点的距离值,保留值较小的一个
  4. 重复执行2、3步骤,直到编历完所有的点

模板

1.基于邻接表的Dijkstra

void Dijkstra(int s){
	memset(dist,INF,sizeof(dist));
	memset(vis,0,sizeof(vis));
	dist[s]=0;
	for(int k=0;k<n;k++){
		int u,mind=INF;
		for(int i=1;i<=n;i++){
			if(dist[i]<mind && !vis[i]){
				mind=dist[i];
				u=i;
			}
		}
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].next_edge){
			int v=edge[i].to,w=edge[i].w;
			if(dist[v]>dist[u]+w){
				dist[v]=dist[u]+w;
			}
		}
	}
}

2.优先队列优化的Dijkstra

struct node{
	int id,dis;
	node(){}
	node(int idd,int diss):id(idd),dis(diss){}
	bool operator <(const node &a) const{
		return a.dis<dis;
	}
};
void Dijkstra(){
	memset(dist,INF,sizeof(dist));
	memset(vis,0,sizeof(vis));
	dist[1]=0;
	priority_queue<node> q;
	q.push(node(1,dist[1]));
	while(!q.empty()){
		node t=q.top();
		q.pop();
		int u=t.id;
		if(vis[u])	continue;
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].next_edge){
			int v=edge[i].to,w=edge[i].w;
			if(dist[v]>dist[u]+w){
				dist[v]=dist[u]+w;
				q.push(node(v,dist[v]));
			}
		}
	}
}

例题

POJ-2387

POJ2387 Til the Cows Come Home

题目描述

Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessie needs her beauty sleep, so she wants to get back as quickly as possible.

Farmer John’s field has N (2 <= N <= 1000) landmarks in it, uniquely numbered 1…N. Landmark 1 is the barn; the apple tree grove in which Bessie stands all day is landmark N. Cows travel in the field using T (1 <= T <= 2000) bidirectional cow-trails of various lengths between the landmarks. Bessie is not confident of her navigation ability, so she always stays on a trail from its start to its end once she starts it.

Given the trails between the landmarks, determine the minimum distance Bessie must walk to get back to the barn. It is guaranteed that some such route exists.

Input

* Line 1: Two integers: T and N

* Lines 2…T+1: Each line describes a trail as three space-separated integers. The first two integers are the landmarks between which the trail travels. The third integer is the length of the trail, range 1…100.

Output

* Line 1: A single integer, the minimum distance that Bessie must travel to get from landmark N to landmark 1.

具体代码
#include<cstdio>
#include<iostream>
#include<cstring>

using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1002,maxe=4002;
int n,m,num_edge;
int dist[maxn],head[maxn];
bool vis[maxn];
struct E{
	int to,next_edge,w;
}edge[maxe];
void add_edge(int u,int v,int w){
	edge[++num_edge].w=w;
	edge[num_edge].to=v;
	edge[num_edge].next_edge=head[u];
	head[u]=num_edge;
}
void Dijkstra(int s){
	memset(dist,INF,sizeof(dist));
	memset(vis,0,sizeof(vis));
	dist[s]=0;
	for(int k=0;k<n;k++){
		int u,mind=INF;
		for(int i=1;i<=n;i++){
			if(dist[i]<mind && !vis[i]){
				mind=dist[i];
				u=i;
			}
		}
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].next_edge){
			int v=edge[i].to,w=edge[i].w;
			if(dist[v]>dist[u]+w){
				dist[v]=dist[u]+w;
			}
		}
	}
}
int main(){
	scanf("%d%d",&m,&n);
	for(int i=0;i<m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add_edge(x,y,z);
		add_edge(y,x,z);
	}
	Dijkstra(1);
	printf("%d\n",dist[n]);
	return 0;
}

POJ-3159

POJ-3159 Candies

题目描述

During the kindergarten days, flymouse was the monitor of his class. Occasionally the head-teacher brought the kids of flymouse’s class a large bag of candies and had flymouse distribute them. All the kids loved candies very much and often compared the numbers of candies they got with others. A kid A could had the idea that though it might be the case that another kid B was better than him in some aspect and therefore had a reason for deserving more candies than he did, he should never get a certain number of candies fewer than B did no matter how many candies he actually got, otherwise he would feel dissatisfied and go to the head-teacher to complain about flymouse’s biased distribution.snoopy shared class with flymouse at that time. flymouse always compared the number of his candies with that of snoopy’s. He wanted to make the difference between the numbers as large as possible while keeping every kid satisfied. Now he had just got another bag of candies from the head-teacher, what was the largest difference he could make out of it?

Input

The input contains a single test cases. The test cases starts with a line with two integers N and M not exceeding 30 000 and 150 000 respectively. N is the number of kids in the class and the kids were numbered 1 through N. snoopy and flymouse were always numbered 1 and N. Then follow M lines each holding three integers A, B and c in order, meaning that kid A believed that kid B should never get over c candies more than he did.

Output

Output one line with only the largest difference desired. The difference is guaranteed to be finite.

具体代码
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=3e4+2;
const int M=150002;
int n,m,num_edge;
int head[maxn],dist[maxn];
bool vis[maxn];
struct Edge{
	int to,w,next_edge;
}edge[M];
struct node{
	int id,dis;
	node(){}
	node(int idd,int diss):id(idd),dis(diss){}
	bool operator <(const node &a) const{
		return a.dis<dis;
	}
};

void add_edge(int u,int v,int w){
	edge[++num_edge].to=v;
	edge[num_edge].w=w;
	edge[num_edge].next_edge=head[u];
	head[u]=num_edge;
}
void Dijkstra(){
	memset(dist,INF,sizeof(dist));
	memset(vis,0,sizeof(vis));
	dist[1]=0;
	priority_queue<node> q;
	q.push(node(1,dist[1]));
	while(!q.empty()){
		node t=q.top();
		q.pop();
		int u=t.id;
		if(vis[u])	continue;
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].next_edge){
			int v=edge[i].to,w=edge[i].w;
			if(dist[v]>dist[u]+w){
				dist[v]=dist[u]+w;
				q.push(node(v,dist[v]));
			}
		}
	}
}
int main(){
	while(~scanf("%d%d",&n,&m)){
		num_edge=0;
		memset(head,0,sizeof(head));
		for(int i=1;i<=m;i++){
			edge[i].next_edge=0;
		} 
		for(int i=0;i<m;i++){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			add_edge(u,v,w);
		}
		Dijkstra();
		printf("%d\n",dist[n]);
	}
	return 0;
}
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值