# 最短路径—dijkstra算法（poj2387）

Til the Cows Come Home
 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 68201 Accepted: 22898

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.

#include<iostream>
#include<cstring>
#define INF 10000000
using namespace std;
int temp[2005][2005],dis[1005];
void dijkstra(int n)
{
int i,min,flag,j,vis[2005]={0};
for(i=1;i<=n;i++) dis[i]=temp[1][i];
for(i=1;i<n;i++)
{
min=INF;
flag=0;
for(j=2;j<=n;j++)
if(min>dis[j]&&!vis[j])
{
min=dis[j];
flag=j;
}
vis[flag]=1;
for(j=2;j<=n;j++)
{
if(dis[j]>min+temp[flag][j]&&!vis[j])
dis[j]=min+temp[flag][j];
}
}
}
int main()
{
int t,i,n,k,m,diss;
while(cin>>t>>n)
{
//memset(temp,INF,sizeof(temp));
for(int i=1;i<=2000;i++) temp[i][i]=0;
for(int i=1;i<=2000;i++)
for(int j=1;j<=2000;j++)
temp[i][j]=INF;
for(int i=1;i<=t;i++)
{
cin>>k>>m>>diss;
if(diss<temp[k][m])
{
temp[k][m]=diss;//双向导通
temp[m][k]=diss;
}
}
dijkstra(n);
//for(int i=1;i<=t;i++) cout<<dis[i]<<endl;
cout<<dis[n]<<endl;
}
return 0;
}

1、最短路径问题介绍

## 2、Dijkstra算法介绍

• 算法特点：

迪科斯彻算法使用了广度优先搜索解决赋权有向图或者无向图的单源最短路径问题，算法最终得到一个最短路径树。该算法常用于路由算法或者作为其他图算法的一个子模块。

• 算法的思路

Dijkstra算法采用的是一种贪心的策略，声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合：T，初始时，原点 s 的路径权重被赋为 0 （dis[s] = 0）。若对于顶点 s 存在能直接到达的边（s,m），则把dis[m]设为w（s, m）,同时把所有其他（s不能直接到达的）顶点的路径长度设为无穷大。初始时，集合T只有顶点s。
然后，从dis数组选择最小值，则该值就是源点s到该值对应的顶点的最短路径，并且把该点加入到T中，OK，此时完成一个顶点，
然后，我们需要看看新加入的顶点是否可以到达其他顶点并且看看通过该顶点到达其他点的路径长度是否比源点直接到达短，如果是，那么就替换这些顶点在dis中的值。
然后，又从dis中找出最小值，重复上述动作，直到T中包含了图的所有顶点。

## 3、Dijkstra算法示例演示

OK，既然确定了一个顶点的最短路径，下面我们就要根据这个新入的顶点V3会有出度，发现以v3 为弧尾的有： < v3,v4 >,那么我们看看路径：v1–v3–v4的长度是否比v1–v4短，其实这个已经是很明显的了，因为dis[3]代表的就是v1–v4的长度为无穷大，而v1–v3–v4的长度为：10+50=60，所以更新dis[3]的值,得到如下结果：

起点  终点    最短路径    长度
v1    v2     无          ∞
v3     {v1,v3}    10
v4     {v1,v5,v4}  50
v5     {v1,v5}    30
v6     {v1，v5,v4,v6} 60