題目傳送門
分析:本題解題邏輯比較複雜,但是一旦理順了思路,也是可以很快\(ac\)的。首先分析下題意,城鎮之間有兩種路徑,雙向、邊權非負的道路,以及單向、邊權可能是負數的航線,並且航線不存在環。抽象成圖模型就是有兩類邊,正權的雙向邊和可以是負權的單向邊,若存在從\(a\)到\(b\)的單向邊,則\(b\)不可能通過一些單向邊或者雙向邊到達\(a\)。如果只當普通的含負權邊的最短路問題,只需要用\(spfa\)演算法就可以求解,但是本題測試資料會卡掉\(spfa\),卡成\(o(nm)\)後,\(25000*150000\)(因為雙向邊,所以是兩倍,而航線還可能有\(50000\),所以是\(150000\)),顯然會超時,因此需要採取更加高效的解法去求解。
spfa寫法
#include using namespace std;
const int n = 25005, m = 150005, inf = 0x3f3f3f3f;
typedef pairpii;
/* spfa直接幹,結果
通過了 14/16個資料
*///存圖
int idx, h[n], e[m], w[m], ne[m];
void add(int a, int b, int c)
int t; // 城鎮數量
int r; // 道路數量
int p; // 航線數量
int s; // 出發點
int dist[n]; //從a點出發,到達每個點的最大距離
bool st[n]; //點i是不是已經進入佇列
//從start出發
void spfa(int start) }}
}}int main()
//處理完無向圖,再來考慮有向邊,航線
while (p--)
spfa(s);
//從s到達城鎮i的最小花費
for (int i = 1; i <= t; i++)
return 0;
}
首先講下預備知識,我們知道,拓撲排序可以求乙個\(dag\)(有向無環圖)的拓撲序列,從而確定任務完成的先後關係,但是容易忽略的是拓撲排序也可以求\(dag\)的最短路徑長度,不管存不存在負權邊。
證明也很簡單,考慮一般的數學歸納法即可證明,假設乙個點的前驅節點離起點的最短距離都確定了,則這個節點離起點的最短距離可以通過前驅結點加上到該節點的邊權的最小值決定。邊界情況是起點的入度為\(0\)時,其後繼節點的最短路就可以直接通過比較確定下來。雖然本題並沒有用這種辦法去求\(dag\)的最短路徑,但是節點最短路的求解順序卻是按照拓撲序來的。
AcWing 342 道路與航線
農夫約翰正在乙個新的銷售區域對他的牛奶銷售方案進行調查。他想把牛奶送到t個城鎮,編號為1 t。這些城鎮之間通過r條道路 編號為1到r 和p條航線 編號為1到p 連線。每條道路 i 或者航線 i 連線城鎮ai到bi,花費為ci。對於道路,0 ci 10,000 然而航線的花費很神奇,花費ci可能是負數...
道路與航線
農夫約翰正在乙個新的銷售區域對他的牛奶銷售方案進行調查。他想把牛奶送到t個城鎮,編號為1 t。這些城鎮之間通過r條道路 編號為1到r 和p條航線 編號為1到p 連線。每條道路 ii 或者航線 ii 連線城鎮ai到bi,花費為ci。對於道路,0 ci 10,0000 ci 10,000 然而航線的花費...
洛谷 P3008 道路與航線
因為有負權邊,所以不能 dijkstra 本題資料還卡 spfa 但是我們發現,有負權的都是有向邊,而且如果把無向邊連成的聯通塊看成乙個點的話,有向邊就連成了乙個 dag,所以我們可以對所有的聯通塊用dij求最短路 在 dag上用拓撲序求最短路 注意 堆優化的 dijkstra 在定義的結構體重載運...