題目鏈接:201703-4 試題名稱: 地鐵修建
題意:
給出兩點之間需要施工的天數,每條路徑可以同時施工,求1到N最少需要幾天。
分析
求最短路徑dijkstra的改編,因爲數據較大,需要使用小根堆的數據結構,可以使用stl的優先隊列,使花費少的放在第一個。因爲施工是同時進行的,所以1到i的最小天數爲其路徑上最大的天數。選擇到達i的最佳鄰接點爲最短的,即當原dis[i] 大於 u 到 i的距離時,dis[i]的距離等於u到i的距離和dis[u]的距離中最大值。例如 2 -> 3距離爲5,1->3距離爲4,dis[2] = 3, dis[1] = 4, 所以dis[3] = max(dis[1], 4); 每次更新距離後,將節點x,dis[x]加入隊列。
代碼
#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 100010;
const int INF = 99999989;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int book[maxn] = {0}, dis[maxn];
int n, m;
typedef struct Node {
int x, c;
Node() {};
Node(int tx, int tc) {
x = tx;
c = tc;
}
friend bool operator < (Node n1, Node n2) {
return n1.c > n2.c;
}
}Node;
vector<Node> v[maxn];
void dij() {
priority_queue<Node> que;
que.push(Node(1, 0));
for (int k = 0; k < n; k++) {
while(!que.empty() && book[que.top().x] != 0)
que.pop();
int u = -1;
if (!que.empty()) { // 得到最小值
u = que.top().x;
que.pop();
}
book[u] = 1;
for (int i = 0; i < v[u].size(); i++) {
int x = v[u][i].x;
if (book[x] == 0 && dis[x] > v[u][i].c) {
// printf(" u = %d x = %d, dis = %d\n", u, x, dis[u]);
dis[x] = max(v[u][i].c, dis[u]); // dis[x]爲u->x的費用,和到u的費用最大值。即路徑上的最大值
// printf("dis[x] = %d\n", v[u][i].c);
que.push(Node(x, dis[x]));
}
}
}
}
/**
5 6
1 2 1
1 3 2
1 4 1
2 3 1
3 5 1
4 5 1
*/
int main(int argc, char** argv) {
int x, y, c;
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &x, &y, &c);
v[x].push_back(Node(y, c));
v[y].push_back(Node(x, c));
}
fill(dis + 1, dis + n + 1, INF);
dis[1] = 1;
dij();
printf("%d", dis[n]);
return 0;
}