Til the Cows Come Home POJ - 2387

版权声明:转载请注明 https://blog.csdn.net/li13168690086/article/details/81977043

写在前面:最短路问题,可以看看这篇文章,来初步了解最短路。

 描述

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.

题目理解

  这道题描述了一个生活场景:有一个在农场外面的挤奶女工,想要回去睡个好觉,但是农场主会给她派活儿。所以她要赶在农场主给她派活儿之前,回到农场,以争取多点时间睡觉。不过有很多条双向连通的回去的路,所以她要规划路线,找到一条距离最短的路。

解题思路

  所以通题意我们知道,这是一道求最短路的问题;再看它的输入输出,发现就是给我们所有顶点的编号、所连点的编号,以及权值。并且要求输出从顶点N到1的最短距离,所以是一道纯单源最短路径问题。不过需要注意的一点是:因为道路是双向的,所以要判断更新两次,只要将起点和终点反过来判断就好,具体见代码。

  下面将通过BF算法和迪杰斯特拉两种算法来求解,对于Bellman-Ford和Dijkstra算法的理解,请看这篇文章

AC代码--BF算法

#include <iostream>
using namespace std;

#define MAX_E 2000
const int INF (100000);

/**
 Bellman-Ford算法,求某点到所有顶点的最短路径。
 */
//从顶点from指向顶点to的权值为cost的边
struct edge{
    int from, to, cost;
};

edge es[MAX_E]; //边
int d[MAX_E]; //最短路径
int V,E; //V是顶点数,E是边数

//求解从顶点s出发到所有点的最短距离
void shortest_path(int s) {
    for(int i = 0; i < V; i++){
        d[i] = INF;
    }
    d[s] = 0;
    while(true){
        bool update = false;
        for(int i = 0; i < E; i++){
            edge e = es[i];
            if(d[e.from] != INF && d[e.to] > (d[e.from] + e.cost)){
                d[e.to] = d[e.from] + e.cost;
                update = true;
            }
            else if(d[e.to] != INF && d[e.from] > (d[e.to] + e.cost)){      //此处和原BF代码不同,反过来添加是因为道路是双向的
                d[e.from] = d[e.to] + e.cost;
                update = true;
            }
        }
        if(!update)
            break;
    }
}

int main(){
    cin >> E >> V;
    for(int i = 0; i < E; i++){
        int a,b,c;
        cin >> a >> b >> c;
        es[i].from = a-1;
        es[i].to = b-1;
        es[i].cost = c;
    }
    shortest_path(V-1);
    cout << d[0];
}

AC代码--Dijkstra算法

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <vector>
using namespace std;

const int MAX_V(10000);     //极限顶点数
const int INF(1<<21);       //极大值

struct edge{
    int to;     //连接点
    int cost;   //权值
};
typedef pair<int, int> P;   //first是最短距离,second是顶点的编号

int V;      //顶点数
vector<edge> G[MAX_V];      //邻接表存储边的值
int d[MAX_V];   //数组存储最短路

void dijkstra(int s){
    priority_queue<P, vector<P>, greater<P> > que;   //greater<P>为从小到大,less<P>从大到小,重载方式
    fill(d, d+V, INF);      //初始化最短路数组,默认为极大值,在最短路情况下
    d[s] = 0;       //将源点的最短路优先赋值为零,以确认所有最短路的出发点
    que.push(P(0,s));       //将源点的最短距离,记忆编号推进优先队列

    while(!que.empty()){    //如果队列里没有元素,则说明所有顶点都被使用过了
        P p = que.top();    //通过优先队列自动排序的特点,从尚未使用过的顶点中选择一个距离最小的顶点
        que.pop();      //然后弹出它,以表示已经被使用
        int v = p.second;   //取顶点的编号
        if(d[v] < p.first)  //如果当前顶点的最短路,大于上一个顶点的最短路,就重新取点
            continue;
        for(int i = 0; i < G[v].size(); i++){   //取得新的距离最小的顶点
            edge e = G[v][i];
            if(d[e.to] > d[v] + e.cost){    //比较它所有可以到达顶点中最小的距离
                d[e.to] = d[v] + e.cost;
                que.push(P(d[e.to], e.to));     //将这个顶点最小的距离,和下一个顶点编号存入优先队列
            }
            else if(d[e.to] > d[v] + e.cost){    //比较它所有可以到达顶点中最小的距离
                d[e.to] = d[v] + e.cost;
                que.push(P(d[e.to], e.to));     //将这个顶点最小的距离,和下一个顶点编号存入优先队列
            }
        }
    }
}

int main(){
    edge e;
    int E;
    
    cin >> E >> V;
    for(int i = 0; i < E; i++){
        int a,b,c;
        cin >> a >> b >> c;
        e.to = b-1;
        e.cost = c;
        G[a-1].push_back(e);
        e.to = a-1;        //因为道路是双向的,所以反过来存储一次
        G[b-1].push_back(e);
    }
    dijkstra(V-1);
    cout << d[0];
}

猜你喜欢

转载自blog.csdn.net/li13168690086/article/details/81977043
今日推荐