单源最短路总结+练习题

单源最短路总结

建图方式

  • 普通无向图+邻接表建图

板子题

1129. 热浪 - AcWing题库

找最短路里的最长路

1128. 信使 - AcWing题库

经典问题,在无向图中找一点使得其他点到该点距离最小

跑n遍最短路即可

1127. 香甜的黄油 - AcWing题库

考察对dijkstra贪心本质的理解,修改了最短路更新的形式

也可以不想这些,用数学构造出一个新的最短路

1126. 最小花费 - AcWing题库

集合之间的最短路问题,有n个连通块,求到终点最少经过几个连通块。

处理方式很简单,只要让每一条边的边权都为1,跑一遍最短路即可,原理也很简单可以自行推导

920. 最优乘车 - AcWing题库

  • 新建源点建图

有一些题看不出来是最短路,是因为他没有直接问你从起点到终点的最短路。

例如超市购物问题/以物易物问题

903. 昂贵的聘礼 - AcWing题库

这时候就可以通过建立一个新的源点0,然后用0作为起点建图

  • 正反建图+spfa

刷到一道题,需要我们找到1~N这条路径里的两个有序的点,一个在前一个在后。

然后让后减前得到最大值。

由于这两个点是在1~N这条路径上,所以最好用spfa

另外,我们让前面最小,让后面最大怎么办?

首先我们就要界定一个中间点i,

然后求出 1~i 的小权值,和i~n的最大权值即可

前者我们以1为起点跑一遍spfa即可

后者我们不可能以i为点跑spfa,这样复杂度过高。

所以需要以n为起点,这样只要一遍就可以得到答案

但是由于可能会有单向边

所以最好反过来建图

341. 最优贸易 - AcWing题库

单源最短路综合运用

dijkstra+dfs

很板,没什么特点。

1135. 新年好 - AcWing题库

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
#define INF 1e10
#define PII pair<int,int>

struct ggg{
  int v;
  int w;
};

ll ans=0;

vector<int> dijkstra(vector<ggg>*gg,int n,int start){
    
    vector<int> dist(n+1,INF);
    vector<bool> flag(n+1);
    priority_queue<PII,vector<PII>,greater<PII>> q;
    dist[start]=0;
    q.push({dist[start],start});
    while(q.size()){
        int u=q.top().second;
        q.pop();
        if(flag[u])continue;
        for(auto i:gg[u]){
            int v=i.v;
            int w=i.w;
            if(dist[v]>dist[u]+w){
                dist[v]=dist[u]+w;
                q.push({dist[v],v});
            }
        }
    }
    return dist;
    
}
signed main(){
    int n,m;
    cin>>n>>m;

    vector<int> t(5);
    for(int i=0;i<5;i++)cin>>t[i];

    vector<ggg> gg[n+1];
    while(m--){
        int u,v,w;
        cin>>u>>v>>w;
        
        gg[u].push_back(ggg{v,w});
        gg[v].push_back(ggg{u,w});
    }
    
    vector<int> a(5);
    vector<int> dist[n+1];
    dist[1]=dijkstra(gg,n,1);
    for(int i=0;i<5;i++){
        a[i]=i;
        dist[t[i]]=dijkstra(gg,n,t[i]);
    }
    
    int ans=0;
    int bns=1e10;
    
    ans=0;
    ans+=dist[1][t[0]];
    for(int i=0;i<4;i++){
      ans+=dist[t[i]][t[i+1]];
    }
    bns=min(bns,ans);
    
    while(next_permutation(a.begin(),a.end())){
        ans=0;
        ans+=dist[1][t[a[0]]];
        for(int i=0;i<4;i++){
          ans+=dist[t[a[i]]][t[a[i+1]]];
        }
        bns=min(bns,ans);
    }
   
    cout<<bns<<endl;
}

dijkstra+二分答案

二分可行性

340. 通信线路 - AcWing题库

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 1e9
#define PII pair<ll,ll>
//#define int long long
struct ggg{
    int v;
    int w;
};

int spfa(vector<ggg>*gg,int n,int k,int K){
    vector<ll> dist(n+1,INF);
    vector<bool> flag(n+1);
    priority_queue<PII,vector<PII>,greater<PII> > q;
    dist[1]=0;
    q.push({0,1});

    while(q.size()){
        int u=q.top().second;
        q.pop();
        if(flag[u])continue;
        flag[u]=1;
        for(auto i:gg[u]){
            int v=i.v;
            int w=i.w;
            if(dist[v]>dist[u]+(w>=k?1:0)){
                dist[v]=dist[u]+(w>=k?1:0);
                q.push({dist[v],v});
            }
        }
    }
    return dist[n]<=K;
}

signed main(){
    int n,p,k;

    cin>>n>>p>>k;
    vector<ggg> gg[n+1];

    while(p--){
        int u,v,w;
        cin>>u>>v>>w;
        gg[u].push_back({v,w});
        gg[v].push_back({u,w});
    }

    int l=0; int r=1e9,mid;
    while(l<r){
        mid=l+r+1>>1;

        if(spfa(gg,n,mid,k)){
            r=mid-1;
        }
        else l=mid;
    }
    if(r!=1e9)
    cout<<r<<endl;
    else cout<<-1<<endl;

}

未完待续…

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

louisdlee.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值