最短路
- 看视频看了好久才理解的啊啊啊啊啊啊啊啊啊啊
- 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; }