图算法~~~

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


Dijkstra算法

在这里插入图片描述

经典例题

https://leetcode.cn/problems/network-delay-time/description/

class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int n, int k) {
        priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>> > q;
        vector<vector<pair<int,int>>> g(n+1);
        for(auto time:times){
            g[time[0]].push_back({time[1],time[2]});
        }
        vector<int>distance(n+1,INT_MAX);
        vector<bool> visited(n+1,0);
        distance[k]=0;
        q.push({0,k});
        while(q.size()){
            int tmp=q.top().second;
            q.pop();
            if(visited[tmp])continue;
            visited[tmp]=true;
            for(auto gg : g[tmp]){
                int w=gg.second,v=gg.first;
                if(!visited[v] && w+distance[tmp]<distance[v]){
                    distance[v]=w+distance[tmp];
                    q.push({distance[v],v});
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            if(distance[i]==INT_MAX){
                return -1;
            }
            ans=max(ans,distance[i]);
        }
        return ans;
    }
};

A星算法

与Dijkstra算法相似,但不同的是,只想快速找到源点到目标点的最小距离。
操作上,在小根堆中比较的是源点到某点的距离+某点到目标点的预估距离。(目的为了更快向目标点靠拢);
在这里插入图片描述

floyd算法

得到图中任意两点之间的最短距离,多源最短路
在这里插入图片描述

例题:洛谷2910

#include <stdio.h>
#include <stdlib.h>
using namespace std;
#include<bits/stdc++.h>
int route[10002];
int g[101][101];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++)cin>>route[i];
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>g[i][j];
        }
    }
    for(int brigde=1;brigde<=n;brigde++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(g[i][j]>(g[i][brigde]+g[brigde][j])){
                    g[i][j]=g[i][brigde]+g[brigde][j];
                }
            }
        }
    }
    int ans=0;
    for(int i=0;i<m-1;i++){
        ans+=g[route[i]][route[i+1]];
    }
    cout<<ans;
    return 0;
}

Bellman-Ford

和Dijkral算法目的相同,但允许有负权边
在这里插入图片描述
在这里插入图片描述
例题:

https://leetcode.cn/problems/cheapest-flights-within-k-stops/description/

这题为了保证每轮最多使最短路边数加一,采用了cur 和 next数组

class Solution {
public:
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
        vector<int> cur(n,INT_MAX);
        cur[src]=0;
        for(int i=0;i<=k;i++){
            vector<int> next(cur);
            for(auto &flight:flights){
                if(cur[flight[0]]!=INT_MAX){
                    next[flight[1]]=min(cur[flight[0]]+flight[2],next[flight[1]]);
                }
            }
            cur=next;
        }
        return cur[dst]==INT_MAX ? -1 : cur[dst];
    }
};

SPFA :对Bellan-Ford的优化(队列)

但只是常数优化,时间复杂度仍为m*n
在这里插入图片描述
在这里插入图片描述

洛谷:3385
判断负环

#include <stdio.h>
#include <stdlib.h>
using namespace std;
#include<bits/stdc++.h>
typedef pair<int,int> PII;
int dis[2001];
int q[6000001];
bool enter[2001];
int cnt[2001];
vector<vector<PII> > g(2001);
int main(){
    int t,n,m;
    cin>>t;
    while(t--){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            dis[i]=INT_MAX;
            enter[i]=0;
            cnt[i]=0;
            g[i].clear();
        }
        for(int i=0;i<m;i++){
            int u,v,w;
            cin>>u>>v>>w;
            g[u].push_back({v,w});
            if(w>=0)g[v].push_back({u,w});
        }
        int l=0,r=0;
        q[r++]=1;
        dis[1]=0;
        enter[1]=true;
        cnt[1]++;
        int flag=1;
        while(l<r){
            int now=q[l++];
            enter[now]=false;
            for(auto &next:g[now]){
                int vv=next.first,ww=next.second;
                if(dis[vv]>(dis[now]+ww)){
                    dis[vv]=dis[now]+ww;
                    if(!enter[vv]){
                        if(cnt[vv]++ == n){
                            flag=0;
                            l=r;
                            break;
                        }
                        q[r++]=vv;
                        enter[vv]=1;
                    }
                }
            }
        }
        if(flag) cout<<"NO"<<'\n';
        else cout<<"YES"<<'\n';
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值