最短路——Dijkstra

最短路——Dijkstra

文章目录

  • 最短路——Dijkstra
    • Dijkstra
    • 算法描述
    • 模板
      • 1.基于邻接表的Dijkstra
      • 2.优先队列优化的Dijkstra
    • 例题
      • POJ-2387
        • 题目描述
        • 具体代码
      • POJ-3159
        • 题目描述
        • 具体代码

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
#include
#include

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
#include
#include
#include
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;
}

你可能感兴趣的:(图论,图论,算法,深度优先,dijkstra)