您的位置:首页 > 其它

Til the Cows Come Home(poj 2387 Dijkstra算法(单源最短路径))

2015-05-01 15:19 357 查看
Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 32824Accepted: 11098
Description

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.
Sample Input

5 5
1 2 20
2 3 30
3 4 20
4 5 20
1 5 100

Sample Output

90

Hint

INPUT DETAILS:

There are five landmarks.

OUTPUT DETAILS:

Bessie can get home by following trails 4, 3, 2, and 1.

Dijkstra算法

1.定义概览

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。

问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)

2.算法描述

1)算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

2)算法步骤:

a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。

b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。

d.重复步骤b和c直到所有顶点都包含在S中。

执行动画过程如下图

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int INF=99999999;                    //设为无穷大
int maps[1005][1005],v[1005],d[1005];  //v表示是否已经过遍历 d表示从源到点当前最短路
int n;

void Dijkstra(int s,int t)
{
int i,j,k,mini;
for(i=1;i<=n;i++)
d[i]=INF;                      //除源点设为0距离外 其他先设为无穷大
d[s]=0;
for(i=1;i<=n;i++)                  //n点循环n次
{
mini=INF;
k=-1;
for(j=1;j<=n;j++)              //在所有未标记点中 选d值最小的点
{
if(!v[j] && d[j]<mini)
{
mini=d[k=j];
}
}
v[k]=1;                         //标记节点
if(k==t)
{
printf("%d\n",d[t]);
return;
}
for(j=1;j<=n;j++)
{
if(!v[j] && d[k]+maps[k][j]<d[j])   //表示从k出发的点,对于所有边,更新相连点
{
d[j]=d[k]+maps[k][j];
}
}
}
}

int main()
{
int T,i,j,x,y,D;
while(scanf("%d %d",&T,&n)!=EOF)
{
memset(v,0,sizeof(v));            //清除标记
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
maps[i][j]=INF;
}
}
for(i=1;i<=T;i++)
{
scanf("%d %d %d",&x,&y,&D);
if(maps[x][y]>D)               //可能有多条路,只记录最短的
maps[x][y]=D,maps[y][x]=D;
}
Dijkstra(1,n);
}
return 0;
}                                          //END Thankyou


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: