poj3662 Telephone Lines
很棒的题目. 简单来说,本题是在无向图上求一条1到N的路径, 使路径上第 K + 1 大的边权尽量小.
本题答案显然有单调性,支付的钱更多时,合法的升级方案一定包含话费少的方案.
于是考虑二分.把升级价格不超过 mid 的边的长度设为0, 然后求从 1 到 N 的最短路长度是否不超过 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 }