# 百练 / 2017研究生推免上机考试 H: Til the Cows Come Home

----------------------------------------

# Til the Cows Come Home

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

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

Given the trails between the landmarks, determine the minimum distance Bessiemust walk to get back to the barn. It is guaranteed that some such routeexists.

* 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. Thethird integer is the length of the trail, range 1..100.

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

5 5

1 2 20

2 3 30

3 4 20

4 5 20

1 5 100

90

INPUT DETAILS:

There are five landmarks.

OUTPUT DETAILS:

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

-----------------------------------------------------

heap Dijskra算法，注意有重边！有重边！有重边！

1. 二维动态数组的声明和初始化

2. operator的重载（类似于java里的comparator interface）

-----------------------------------------------------

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

struct Node {
int id;
int len;
};

struct lenLess {
bool operator() (const Node &n1, const Node &n2) {
return n1.len > n2.len;
}
} len_less;

int main()
{
int N=0, T=0, i=0, j=0, h=0, t=0, c=0;
cin >> T >> N;
int** graph = new int*[N];			// 创建二维动态数组，由于cost~[1,100]，故用char类型
for (i=0; i<N; i++)
{
graph[i] = new int[N];
for (j=0; j<N; j++)
{
graph[i][j] = 0;
}
}
for (i=0; i<T; i++)
{
cin >> h >> t >> c;
h--;								// 符合C语言下标从0开始的习惯
t--;
if (graph[h][t] == 0)				// 第一条边
{
graph[h][t] = c;
graph[t][h] = c;
}
else								// 有重边
{
graph[h][t] = min(graph[h][t], c);	// 取短的那个
graph[t][h] = min(graph[t][h], c);	// 取短的那个
}

}

// 初始化
deque<Node> dijk;							// N-1到地图上其他各点距离的N-1维双端队列
for (i=0; i<N-1; i++)
{
Node aN;
aN.id = i;
if (graph[N-1][i] != 0)
{
aN.len = graph[N-1][i];
}
else
{
aN.len = INT_MAX;
}
dijk.push_back(aN);
}

// 循环直到N-1到0的路径最小
int cMin = INT_MAX;								// 当次循环最小路径
int iMin = N-1;									// 当次循环最小路径对应的节点
deque<Node>::iterator it;
while (iMin != 0)
{
make_heap(dijk.begin(), dijk.end(), len_less);	// 维护最小堆
Node nMin = dijk.front();						// 此轮被弹出的最短距离节点
cMin = nMin.len;
iMin = nMin.id;
dijk.pop_front();
for (it = dijk.begin(); it != dijk.end(); it++)
{
if (graph[iMin][it->id] != 0)				// 如果it->id与iMin连通
{
it->len = min(cMin + graph[iMin][it->id], it->len);	// 更新距离
}
}
}

cout << cMin;

for (i=0; i<N; i++)
{
delete[] graph[i];
}
delete[] graph;
return 0;
}