<—点个赞吧QwQ
宣传一下算法提高课整理{:target=”_blank”}
在郊区有 $N$ 座通信基站,$P$ 条 双向 电缆,第 $i$ 条电缆连接基站 $A_i$ 和 $B_i$。
特别地,$1$ 号基站是通信公司的总站,$N$ 号基站位于一座农场中。
现在,农场主希望对通信线路进行升级,其中升级第 $i$ 条电缆需要花费 $L_i$。
电话公司正在举行优惠活动。
农产主可以指定一条从 $1$ 号基站到 $N$ 号基站的路径,并指定路径上不超过 $K$ 条电缆,由电话公司免费提供升级服务。
农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。
求至少用多少钱可以完成升级。
输入格式
第 $1$ 行:三个整数 $N,P,K$。
第 $2..P+1$ 行:第 $i+1$ 行包含三个整数 $A_i,B_i,L_i$。
输出格式
包含一个整数表示最少花费。
若 $1$ 号基站与 $N$ 号基站之间不存在路径,则输出 $\-1$。
数据范围
$0 \\le K < N \\le 1000$,
$1 \\le P \\le 10000$,
$1 \\le L_i \\le 1000000$
输入样例:
5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6
输出样例:
4
思路
因为是求最大值,所以考虑二分。
假设我们的价格最终是$ans$,那么价格$x\le ans$一定不够,而价格$y\ge ans$一定够,所以这道题满足二段性,可以二分。
二分时我们要注意$check$函数时统计超过当前价值的路径上一共有几条,也就是要免费几条路。
这里的最短路我选用了$\text{Dijkstra}$
代码
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef pair <int,int> PII;
const int N = 1010,M = 20010;
int n,m,k;
int h[N],ne[M],idx = 0;
struct edge {
int to,w;
}edges[M];
int dist[N];
bool st[N];
void add (int a,int b,int c) {
edges[idx] = {b,c};
ne[idx] = h[a];
h[a] = idx++;
}
bool check (int max_w) {
memset (dist,0x3f,sizeof (dist));
memset (st,false,sizeof (st));
dist[1] = 0;
priority_queue <PII,vector <PII>,greater <PII>> heap;
heap.push ({0,1});
while (!heap.empty ()) {
int t = heap.top ().second;
heap.pop ();
if (st[t]) continue;
st[t] = true;
for (int i = h[t];~i;i = ne[i]) {
int j = edges[i].to,w = edges[i].w > max_w;
if (dist[j] > dist[t] + w) {
dist[j] = dist[t] + w;
heap.push ({dist[j],j});
}
}
}
return dist[n] <= k;
}
int main () {
memset (h,-1,sizeof (h));
scanf ("%d%d%d",&n,&m,&k);
int max_w = 0;
while (m--) {
int a,b,c;
scanf ("%d%d%d",&a,&b,&c);
max_w = max (max_w,c);
add (a,b,c),add (b,a,c);
}
int l = 0,r = max_w + 1;
while (l < r) {
int mid = l + r >> 1;
if (check (mid)) r = mid;
else l = mid + 1;
}
if (l == max_w + 1) printf ("-1\n");
else printf ("%d\n",l);
return 0;
}
没懂
为什么
建议看一下提高课视频
我也解释不清,y总讲得更好
算了,我还是解释一下吧
这里二分判断max_w是否满足要求,然后呢跑最短路,若这条边权值大于max_w,那么这条边就需要免费权值+1,否则不变,最后到终点的最短路就是max_w所需的最少免费边数
这个不应该是判断大于mid吗