傳送門:
Telephone Lines
題意:
從第1點走到第N點(不必經過所有點)經過的邊,權重最大的儘量小,並且有K條道路可當作權重為0,求最大權重。
思路:
二分搜最大權重,跑一個特殊的dijkstra算法,Key值是該點剩餘的K,需注意最後答案可能為0。
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
int N,P,K, a,b,l, mx;
vii G[1005];
bool visit[1005];
void init(){
N = getint(), P = getint(), K = getint();
mx = 0;
while(P--){
a = getint(), b = getint(), l = getint();
mx = max(mx, l);
G[a].PB(MP(b,l));
G[b].PB(MP(a,l));
}
}
typedef priority_queue<pii> pq;
pq q;
int karr[1005];
inline bool suc(int x){
memset(visit, 0, sizeof(visit));
fill(karr, karr+N+1, -INT_MAX);
q = pq();
karr[1] = K;
q.push(MP(K,1));
while(!q.empty()){
int k = q.top().X, v = q.top().Y;
q.pop();
if(visit[v]) continue;
visit[v] = 1;
for(int i=0;i<G[v].size();i++){
int vv = G[v][i].X, len = G[v][i].Y;
if(!visit[vv] and ((len<=x and k>karr[vv]) or (k>0 and k-1>karr[vv]))){
if(vv == N) return true;
if(len <= x){
q.push(MP(k, vv));
karr[vv] = k;
}
else{
q.push(MP(k-1, vv));
karr[vv] = k-1;
}
}
}
}
return false;
}
void sol(){
visit[1] = 1;
#define mid ((L+R)>>1)
int L = -1, R = mx; // 注意L為-1才能做到 suc(0) 的case
if(!suc(mx)){
puts("-1");
return;
}
while(R-L>1) suc(mid) ? R=mid : L=mid;
cout << R << endl;
}
int main(){
init();
sol();
}