ACWing 340通信线路(两种做法)

原题:

在郊区有 N 座通信基站,P 条 双向 电缆,第 i 条电缆连接基站AiAi和BiBi。

特别地,1 号基站是通信公司的总站,N 号基站位于一座农场中。

现在,农场主希望对通信线路进行升级,其中升级第 i 条电缆需要花费LiLi。

电话公司正在举行优惠活动。

农产主可以指定一条从 1 号基站到 N 号基站的路径,并指定路径上不超过 K 条电缆,由电话公司免费提供升级服务。

农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。

求至少用多少钱可以完成升级。

输入格式

第1行:三个整数N,P,K。

第2..P+1行:第 i+1 行包含三个整数Ai,Bi,LiAi,Bi,Li。

输出格式

包含一个整数表示最少花费。

扫描二维码关注公众号,回复: 10766963 查看本文章

若1号基站与N号基站之间不存在路径,则输出”-1”。

数据范围

0K<N10000≤K<N≤1000,
1P100001≤P≤10000,
1Li10000001≤Li≤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
原题地址:https://www.acwing.com/problem/content/342/

 

两种解法一种是二分+01图跑最短路(最优解),另一种是分层图跑spfa(次解)

二分+01跑最短路check

可以二分答案x,然后check1到n的路径最少走几条大于x的路,如果大于x的路小于等于k就返回true,否则返回false,具体check算法:以x为阈值,大于x的边为1,小于等于x的边为0,然后跑最短路即可

时间复杂度:O(n*mlogm)

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;

const int Maxn = 1e3 + 10;
const int inf = 0x3f3f3f3f;

struct Edge{
    int v, w;
    Edge(int v, int w): v(v), w(w) {}
};

struct Node{
    int v, d;
    Node(int v, int d) : v(v), d(d) {}
    bool operator > (const Node& B) const{
        return d > B.d;
    }
};

vector<vector<Edge> > G(Maxn);
int dist[Maxn];
bool visit[Maxn];

bool check(int n, int k, int x)
{
    priority_queue<Node, vector<Node>, greater<Node> > pq;
    memset(dist, inf, sizeof(dist));
    memset(visit, 0, sizeof(visit));
    dist[1] = 0;
    pq.push(Node(1, 0));
    while(!pq.empty()){
        Node t = pq.top(); pq.pop();
        int u = t.v;
        if(visit[u]) continue;
        
        for(int i=0; i<G[u].size() ;i++){
            int v = G[u][i].v;
            int w = G[u][i].w;
            if(w > x) w = 1;
            else w = 0;
            if(!visit[v] && dist[v] > dist[u] + w){
                dist[v] = dist[u] + w;
                pq.push(Node(v, dist[v]));
            }
        }
    }
    
    if(dist[n] <= k) return true;
    else return false;
}

int main()
{
    int n, m, p;
    cin>>n>>m>>p;
    for(int i=0; i<m ;i++){
        int u, v, w;
        cin>>u>>v>>w;
        G[u].push_back(Edge(v, w));
        G[v].push_back(Edge(u, w));
    }
    
    int l = 0, r = inf;
    while(l < r){
        int m = l + r >> 1;
        if(check(n, p, m)) r = m;
        else l = m + 1;
    }
    
    if(r == inf) cout<<-1;
    else cout<<r;
    
    return 0;
}

分层图跑spfa

这个题可以看做是一个K+1层的图,然后把边变成免费操作可以看成是两点间有一条权值为0的边,但是经过这条边的同时会进入下一层图,因为最多只有K+1层图,所以最多只能通过K次0权边。因此在这种分层图里跑最短路,然后每一层到n结点的路径的最小值就是答案。最坏情况下的时间复杂度应该是O(n*k*m),本该超时的,但是这个题居然能过,说明是数据水了,所以这个只能是次优解

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;

struct Edge{
    int v, w;
    Edge(int v, int w): v(v), w(w) {}
};

struct Node{
    int v, d, p;
    Node(int v, int d, int p) : v(v), d(d), p(p) {}
};

const int Maxn = 1e3 + 10;
const int inf = 0x3f3f3f3f;
vector<vector<Edge> > G(Maxn);
int dist[Maxn][Maxn];

void spfa(int n, int k)
{
    memset(dist, inf, sizeof(dist));
    dist[1][0] = 0;
    queue<Node> q;
    q.push(Node(1, 0, 0));
    while(!q.empty()){
        Node t = q.front() ;q.pop();
        int u = t.v;
        int p = t.p;
        
        for(int i=0; i<G[u].size() ;i++){
            int v = G[u][i].v;
            int w = G[u][i].w;
            
            if(w > 0 && dist[v][p] > max(w, dist[u][p])){
                dist[v][p] = max(w, dist[u][p]);
                q.push(Node(v, dist[v][p], p));
            }
            else if(w == 0 && p != k && dist[v][p+1] > dist[u][p]){
                dist[v][p+1] = dist[u][p];
                q.push(Node(v, dist[v][p+1], p+1));
            }
        }
    }
}

int main()
{
    int n, m, k;
    cin>>n>>m>>k;
    for(int i=0; i<m ;i++){
        int u, v, w;
        cin>>u>>v>>w;
        G[u].push_back(Edge(v, w));
        G[u].push_back(Edge(v, 0));
        G[v].push_back(Edge(u, w));
        G[v].push_back(Edge(u, 0));
    }
    
    spfa(n, k);
    int ans = inf;
    for(int i=k; i>=0 ;i--)
        ans = min(ans, dist[n][i]);
    
    if(ans != inf) cout<<ans;
    else cout<<-1;

    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wulichenai/p/12694599.html