最短路

  • 看视频看了好久才理解的啊啊啊啊啊啊啊啊啊啊
  • Dijkstra(单源路径,贪心原理,负权边别来沾边)堆优化法时间复杂度o(mlogn)

我只会写堆化版,朴素版太过复杂了(自我感觉)

这是cf中的dijkstra题目,1900的难度,当时卡了三天。。。。

#include<iostream>
#include<vector>
#include<queue>
#include<cstdio>
using namespace std;
#define int long long
const int inf = 0x3f3f3f3f3f3f3f3f;
vector<pair<int, int>> vr[400010];
int dis[200010], book[200010], pre[200010],now[200010];
void dijkstra(){
    memset(dis, inf, sizeof(dis));
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
    dis[1] = 0;
    q.push(make_pair(0, 1));
    while (!q.empty()) {
        int x = q.top().first;
        int y = q.top().second;
        q.pop();
        if (book[y] == 1)continue;
        book[y] = 1;
        for (auto it : vr[y])
            if (it.second + x < dis[it.first]) {
                dis[it.first] = it.second + x;
                pre[it.first] = y;
                q.push(make_pair(dis[it.first], it.first));
            }
                
    }
}
void solve(){
    int n, m;
    scanf("%lld %lld", &n, &m);
    while (m--){
        int u, v, w;
        scanf("%lld %lld %lld", &u, &v, &w);
        vr[u].push_back(make_pair(v, w));
        vr[v].push_back(make_pair(u, w));
    }
    dijkstra();
    if (dis[n] < inf) {
        int noww = n, cnt = 0;
        while (noww >= 1) {
            now[cnt++] = noww;
            noww = pre[noww];
        }
        for (int i = cnt - 1; i >= 0; i--)printf("%d ",now[i]);
    }
    else printf("-1");
}
signed main(){
    int t = 1;
    while (t--)
        solve();
    return 0;
}
  •  Floyd(可处理多源路径问题,并可接受负权边)时间复杂度o(n^3)
void floyd() {
    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                if (dis[i][j] > dis[i][k] + dis[k][j])
                    dis[i][j] = dis[i][k] + dis[k][j];
}
void solve() {
    memset(dis, inf, sizeof(dis));//初始化为无限大
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        dis[u][v] = w;
        dis[i][i] = 0;//本身距离为0
        }
}
  •  SPFA(求单源最短路问题,支持负权边)时间复杂度o(nm)

  洛谷p3385 负环

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N = 2e5 + 10, inf = 0x3f3f3f3f3f3f3f3f;
int dis[N], cnt[N];
bool book[N];//表示此元素是否在队列中
void SPFA(int n,vector<pair<int,int>> vt[]) {
    memset(dis, inf, sizeof(dis));
    memset(book, false, sizeof(book));
    memset(cnt, 0, sizeof(cnt));
    queue<int> q;
    dis[1] = 0;
    book[1] = true;
    //cnt[1] = 1;
    q.push(1);
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        book[x] = false;//弹出后不在队列中
        for (auto it : vt[x]) {
            if (dis[it.first] > dis[x] + it.second) {
                dis[it.first] = dis[x] + it.second;
                cnt[it.first]++;
                if (cnt[it.first] >= n) {//计数器大于n,说明该元素被加入队列n次,此时肯定存在负环使得此元素的最短路越来越小
                    cout << "YES" << endl;
                    return;
                }
                if (!book[it.first]) {
                    q.push(it.first);
                    book[it.first] = true;
                }
            }
        }
    }
    cout << "NO" << endl;
}
void solve() {
    int n, m;
    cin >> n >> m;
    vector<pair<int, int>> vt[n+1];
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        vt[u].push_back(make_pair(v, w));
        if (w >= 0)vt[v].push_back(make_pair(u, w));
    }
    SPFA(n,vt);
    //vt->clear();
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--)solve();
    return 0;
}

 

 
 
 
 
 
posted @ 2023-07-31 10:30  DLSQS  阅读(42)  评论(0)    收藏  举报