当前位置: 代码迷 >> 综合 >> AcWing 340. 通信线路
  详细解决方案

AcWing 340. 通信线路

热度:96   发布时间:2023-12-22 12:16:37.0

题目链接

样例解释

1.png

二分 + 最短路模型

进一步解释:题目要求我们最多把k条边置为0,使得1到N号的剩余路线中,最大的花费最小

那么我们可以假设一个解为x,只要egdei≤xegde_i \leq xegdei?x的边都置为0。egdei≥xegde_i \geq xegdei?x都置为1,这样我们只关注那些等于1的边,从1到N等于1的边个数小于等于k(即要去掉边的个数≤k\leq kk),那么这个解就是成立的!

因此这个题是可以使用二分来做的, 图示如下
2.png


3.png


4.png


5.png

到了这里,下面就是求解从1到N边权为1最少条数的路径,发现这就完美转化为了一个最短路问题。因为只有边权为0和1的边,写一个不会TLE的解法就可。还是y总的代码写得漂亮就抄y总的吧?

注意二分的起始区间是[0,1+max(L1,L2,....Lm)][0,1 + max(L_1, L_2, .... L_m)][0,1+max(L1?,L2?,....Lm?)], 当最终解是1+max(L1,L2,....Lm)1 + max(L_1, L_2, .... L_m)1+max(L1?,L2?,....Lm?)时,表示方案无解(因为农夫的花费怎么也不可能比最大的边还要大嘛)

代码

用朴素版的dijkstra能过

#include<iostream>
#include<cstring>
using namespace std;const int N = 1e3 + 10, INF = 0x3f3f3f3f;int n, m, k;
int g[N][N];
int dist[N];
bool st[N];int dijkstra(int x)
{
    memset(st, 0, sizeof st);memset(dist, 0x3f, sizeof dist);dist[1] = 0;for(int i = 0; i < n - 1; i++){
    int u = -1;for(int j = 1; j <= n; j++){
    if(!st[j] && (u == -1 || dist[j] < dist[u])) u = j;}if(st[n]) break;st[u] = true;for(int j = 1; j <= n; j++){
    if(g[u][j] == INF) continue;int d = g[u][j] > x;dist[j] = min(dist[j], dist[u] + d);}}return dist[n];
}int main()
{
    cin >> n >> m >> k;memset(g, 0x3f, sizeof g);int maxv = -INF;for(int i = 0; i < m; i++){
    int a, b, c;cin >> a >> b >> c;g[a][b] = g[b][a] = min(c, g[a][b]);maxv = max(maxv, c);}int l = 0, r = maxv + 1;while(l < r){
    int mid = l + r >> 1;if(dijkstra(mid) <= k) r = mid;else l = mid + 1;}if(l == maxv + 1) l = -1;cout << l << endl;return 0;
}