算法提高课-图论-单源最短路的扩展应用-AcWing 1137. 选择最佳线路:多源最短路、虚拟源点
生活随笔
收集整理的這篇文章主要介紹了
算法提高课-图论-单源最短路的扩展应用-AcWing 1137. 选择最佳线路:多源最短路、虚拟源点
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目分析
來源:acwing
分析:
本題有多組測試數據,如果對每個源點暴力使用dijkstra,會超時。
好的做法:建立虛擬源點S,讓S到所有真實起點的邊權為0,這樣原問題就可以轉換為從虛擬源點S到終點的單元最短路問題。
建立虛擬源點的寫法:會TLE,對了5個點
嘗試對每個起點進行dijkstra,也會TLE,結果對了7個點!!天哪。
第三次嘗試:寫了反向dijkstra,即從終點為起點,反向建邊,結果還是TLE,對了9個點,就有點生氣!
代碼1(對了5個點)
#include<bits/stdc++.h> using namespace std; const int N = 1010, INF = 0x3f3f3f3f; const int M = 20010; typedef pair<int,int> PII; #define x first #define y second int n, m, s; int h[N],e[M],w[M],ne[M],idx; int dist[N]; bool st[N];void add(int a, int b, int c){e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++; }int dijkstra(){memset(dist, 0x3f, sizeof dist);memset(st, 0, sizeof st);dist[0] = 0;priority_queue<PII, vector<PII>, greater<PII>> heap;heap.push({0,0});while(heap.size()){auto t = heap.top();heap.pop();int ver = t.y, distance = t.x; if(st[ver]) continue;st[ver] = true;for(int i = h[ver]; ~i; i = ne[i]){int j = e[i];if(dist[j] > distance + w[i]){dist[j] = distance + w[i];heap.push({dist[j], j});}}}if(dist[s] == INF) return -1;return dist[s]; }int main(){while(scanf("%d%d%d",&n, &m, &s) != -1){memset(h, -1, sizeof h);int p, q, t;while(m --){scanf("%d%d%d", &p, &q, &t);add(p, q, t);}int w;scanf("%d",&w);for(int i = 0; i< w; i++){int ver;scanf("%d",&ver);add(0,ver, 0);}printf("%d\n", dijkstra());} }代碼2(對了9個點)
#include<bits/stdc++.h> using namespace std; const int N = 1010, INF = 0x3f3f3f3f; const int M = 20010; typedef pair<int,int> PII; #define x first #define y second int n, m, s; int h[N],e[M],w[M],ne[M],idx; int dist[N]; bool st[N]; int path[N];void add(int a, int b, int c){e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++; }void dijkstra(){memset(dist, 0x3f, sizeof dist);memset(st, 0, sizeof st);priority_queue<PII, vector<PII>, greater<PII>> heap;heap.push({0,s});dist[s] = 0;while(heap.size()){auto t = heap.top();heap.pop();int ver = t.y, distance = t.x; if(st[ver]) continue;st[ver] = true;for(int i = h[ver]; ~i; i = ne[i]){int j = e[i];if(dist[j] > distance + w[i]){dist[j] = distance + w[i];heap.push({dist[j], j});}}} }int main(){while(scanf("%d%d%d",&n, &m, &s) != -1){memset(h, -1, sizeof h);int p, q, t;while(m --){scanf("%d%d%d", &p, &q, &t);add(q, p, t);}dijkstra();int w, res = INF;scanf("%d",&w);int ver;while(w --){cin >> ver;res = min(res, dist[ver]);}if(res == INF) res = -1;printf("%d\n", res);} }代碼3(ac:也是虛擬源點的寫法,結果就ac了,真是奇了怪了!!!)
#include<bits/stdc++.h> #define x first #define y second using namespace std;typedef pair<int, int> PII; //建立虛擬源點0 const int N = 1010, M = 40010, INF = 0x3f3f3f3f; int n, m, s; int h[N], e[M], w[M], ne[M], idx; int dist[N]; bool st[N];void add(int a, int b, int c) {e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; } int dijkstra() {memset(dist, 0x3f, sizeof dist);memset(st, 0, sizeof st);priority_queue<PII, vector<PII>, greater<PII>> heap;heap.push({0, 0});dist[0] = 0;while (heap.size()) {PII t = heap.top();heap.pop();int ver = t.y, distance = t.x;if (st[ver]) continue;st[ver] = true;for (int i = h[ver]; ~i; i = ne[i]) {int j = e[i];if (dist[j] > distance + w[i]) {dist[j] = distance + w[i];heap.push({dist[j], j});}}}if (dist[s] == INF) return -1;return dist[s]; } int main() {while (scanf("%d%d%d", &n, &m, &s)!= -1) {memset(h, -1, sizeof h);idx = 0;int x;while (m--) {int a, b, c;scanf("%d%d%d", &a, &b, &c);add(a, b, c);}scanf("%d", &x);while (x--) {int stop;scanf("%d", &stop);add(0, stop, 0);}cout << dijkstra() << endl;}return 0; }題目來源
https://www.acwing.com/problem/content/description/1139/
總結
以上是生活随笔為你收集整理的算法提高课-图论-单源最短路的扩展应用-AcWing 1137. 选择最佳线路:多源最短路、虚拟源点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 算法提高课-数学知识-矩阵乘法-AcWi
- 下一篇: CSP认证201412-2Z字形扫描[C