Great question. In simple terms, this question is to find a path from 1 to N on an undirected graph such that the K + 1th largest edge weight on the path is as small as possible.
The answer to this question is obviously monotonic. When paying more money, a legitimate upgrade plan must include a plan with less call charges.
So consider bisection. Set the length of the edge whose upgrade price does not exceed mid as 0, and then find out whether the length of the shortest path from 1 to N does not exceed K.
1 #include <cstdio>
2 #include <algorithm>
3 #include <cstring>
4 #include <queue>
5 #include <vector>
6 #include <iostream>
7
8 using namespace std;
9 typedef pair<int, int> Pa;
10 const int MAXN = 1e3 + 20;
11 const int MAXP = 1e4 + 20;
12 const int MAXL = 1000000 + 20;
13
14 inline int read()
15 {
16 int x = 0; char ch = getchar();
17 while(!isdigit(ch)) ch = getchar();
18 while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
19 return x;
20 }
21
22 int N, P, K;
23
24 namespace edges
25 {
26 struct edge
27 {
28 int from, to, cost;
29 edge(int u = 0, int v = 0, int c = 0) : from(u), to(v), cost(c) {}
30
31 bool operator <(const edge &rhs) const{
32 return cost < rhs.cost;
33 }
34 }E[MAXP];
35
36 inline void addedge(int u, int v, int c)
37 {
38 static int cnt = 1;
39 E[cnt++] = edge(u, v, c);
40 }
41
42 inline void init()
43 {
44 sort(E + 1, E + P + 1);
45 }
46 }
47
48 namespace dij
49 {
50 struct edge
51 {
52 int to, cost;
53 edge(int v = 0, int c = 0) : to(v), cost(c) {}
54 };
55
56 vector<edge> g[MAXN];
57 int d[MAXN];
58
59 inline void addedge(int u, int v, int c)
60 {
61 g[u].push_back(edge(v, c));
62 g[v].push_back(edge(u, c));
63 }
64
65 inline void init()
66 {
67 for(int i = 0; i <= N; i++)
68 g[i].clear();
69 }
70
71 inline bool tension(const int &sml, int &big)
72 {
73 return sml < big ? (big = sml, true) : false;
74 }
75
76 inline int dijkstra(int s, int t)
77 {
78 deque<Pa> q;
79 memset(d, 0x3f, sizeof(d));
80
81 d[s] = 0;
82 q.push_front(Pa(0, s));
83
84 while(!q.empty())
85 {
86 Pa p = q.front(); q.pop_front();
87 int u = p.second;
88 if(d[u] < p.first) continue;
89
90 for(int i = 0; i < (int) g[u].size(); i++)
91 {
92 edge e = g[u][i];
93 if(tension(d[u] + e.cost, d[e.to]))
94 {
95 if(e.cost == 1) q.push_back(Pa(d[e.to], e.to));
96 else q.push_front(Pa(d[e.to], e.to));
97 }
98 }
99 }
100 return d[t];
101 }
102 }
103
104 inline bool check(int fare)
105 {
106 using namespace edges;
107
108 dij::init();
109 for(int i = 1; i <= P; i++)
110 {
111 edge e = E[i];
112 dij::addedge(e.from, e.to, e.cost > fare ? 1 : 0);
113 }
114
115 return dij::dijkstra(1, N) > K ? false : true;
116 }
117
118 int main()
119 {
120 // freopen("p1948.txt", "r", stdin);
121 cin>>N>>P>>K;
122
123 int u, v;
124 for(int i = 1; i <= P; i++)
125 {
126 u = read(), v = read();
127 edges::addedge(u, v, read());
128 }
129
130 //edges::init();
131
132 int l = 0, r = MAXL;
133 #define mid (((l) + (r)) >> 1)
134 while(l < r)
135 {
136 if(check(mid)) r = mid;
137 else l = mid + 1;
138 }
139
140 if(l == MAXL) cout<<-1<<endl;
141 else cout<<l<<endl;
142 return 0;
143 }