道路和航線 題解

2022-06-26 08:21:12 字數 2559 閱讀 8734

題目描述

farmer john 正在乙個新的銷售區域對他的牛奶銷售方案進行調查。他想把牛奶送到 \(t\) 個城鎮 ,編號為 \(1\) 到 \(t\)。這些城鎮之間通過 \(r\) 條道路(編號為 \(1\) 到 \(r\))和 \(p\) 條航線(編號為 \(1\) 到 \(p\))連線。每條道路 \(i\) 或者航線 \(i\) 連線城鎮 \(a_i\) 到 \(b_i\),花費為 \(c_i\)。

對於道路,\(0 \le c_i \le 10^4\),然而航線的花費很神奇,花費 \(c_i\) 可能是負數。道路是雙向的,可以從 \(a_i\) 到 \(b_i\),也可以從 \(b_i\) 到 \(a_i\),花費都是 \(c_i\)。然而航線與之不同,只可以從 \(a_i\) 到 \(b_i\)。

事實上,由於最近恐怖主義太囂張,為了社會和諧,出台了一些政策保證:如果有一條航線可以從 \(a_i\) 到 \(b_i\),那麼保證不可能通過一些道路和航線從 \(b_i\) 回到 \(a_i\)。由於 fj 的奶牛世界公認十分給力,他需要運送奶牛到每乙個城鎮。他想找到從傳送中心城鎮 \(s\) 把奶牛送到每個城鎮的最便宜的方案,或者知道這是不可能的。

輸入格式

第一行為四個空格隔開的整數:\(t, r, p,s\);

第二到第 \(r+1\) 行:三個空格隔開的整數(表示一條道路):\(a_i, b_i\) 和 \(c_i\);

第 \(r+2\) 到 \(r+p+1\) 行:三個空格隔開的整數(表示一條航線):\(a_i, b_i\) 和 \(c_i\)。

輸出格式

輸出 \(t\) 行,第 \(i\) 行表示到達城鎮 \(i\) 的最小花費,如果不存在輸出no path

樣例輸入

6 3 3 4 

1 2 5

3 4 5

5 6 10

3 5 -100

4 6 -100

1 3 -10

樣例輸出
no path 

no path

5 0

-95

-100

樣例說明

一共六個城鎮。在 \(1\) 和 \(2\),\(3\) 和 \(4\),\(5\) 和 \(6\) 之間有道路,花費分別是 \(5,5,10\)。同時有三條航線:\(3\to 5\),\(4\to 6\) 和 \(1\to 3\),花費分別是 \(-100,-100,-10\)。fj 的中心城鎮在城鎮 \(4\)。fj 的奶牛從 \(4\) 號城鎮開始,可以通過道路到達 \(3\) 號城鎮。然後他們會通過航線達到 \(5\) 和 \(6\) 號城鎮。但是不可能到達 \(1\) 和 \(2\) 號城鎮。

資料範圍

對於全部資料,\(1\le t\le 2.5\times 10^4,1\le r,p\le 5\times 10^4,1\le a_i,b_i,s\le t\)。保證對於所有道路,\(0 \le c_i \le 10^4\),對於所有航線,\(-10^4 \le c_i \le 10^4\)。

分析題目大意就是求 s 到任一點的最短路,因為圖中有負邊權,所以優先考慮到用 spfa。但是不加優化不加快讀此題會卡一到兩個點。

所以還是老老實實跑 dijkstra 吧。

很明顯單純的 dij 跑負邊權會出問題,反例也很好找。

但是題目中給了個條件,意思是如果一條邊是航線,不僅不存在負權迴路,它還會把圖分割成兩個獨立的連通塊(也就是說,如果把這條邊去掉,它所連的兩部分是不連通的)。

如果我們把每個連通塊縮成乙個點,那麼整個圖就變成了 dag,要找起點 s 到每個點的最短路,直接拓撲排序跑一遍就可以。

// 先放乙個spfa的優化版本

void spfa_deque(int now) ;

memset(dis, 0x3f, sizeof(dis));

dis[now] = 0;

q.push_back(node(now, 0));

inque[now] = true;

while (!q.empty()) else

inque[to] = true;}}

} }}

void dijkstra(int x) 

while (!q.empty())

}// 前面的判斷是為了防止負邊權造成dis值減小,影響最後的判斷是否連通

// 如果dis[now]==inf,說明起點與它不連通,鬆弛沒有意義

if (dis[now] < inf && dis[to] > dis[now] + e[i].w)

}} }

}void topsort()

} memset(dis, 0x3f, sizeof(dis)); // 初始化dij的陣列跑最短路用

dis[s] = 0;

while (!tpque.empty())

}// 主函式中處理完雙向道路之後,呼叫該函式尋找連通塊

// belong陣列儲存當前結點屬於哪個連通塊

void dfs(int x) }}

// 最後判斷如果dis值等於inf,則無法到達,否則輸出dis值即可

道路和航線

試題描述 farmer john 正在乙個新的銷售區域對他的牛奶銷售方案進行調查。他想把牛奶送到 t 1 t 2.5 10 4 個城鎮 編號為 1 到 t。這些城鎮之間通過 r 條道路 編號為 1 到 r 和 p 條航線 編號為 1 到 p 連線。每條道路 i 或者航線 i 連線城鎮 ai到 bi,...

道路和航線

題目描述 一張圖,有由t個節點,r條雙向邊和p條單向邊組成,每條邊有邊權且可能存在負權,求能否從s到達每個節點並且輸出最小花費。思路首先第一想法,把這張圖建出來,在跑一遍spfa即可,然而它顯然被卡了,不過似乎可以用雙端佇列優化水過去。接下就是正解。我們考慮對於所有的道路,都是正權,我們可以用dij...

道路與航線

農夫約翰正在乙個新的銷售區域對他的牛奶銷售方案進行調查。他想把牛奶送到t個城鎮,編號為1 t。這些城鎮之間通過r條道路 編號為1到r 和p條航線 編號為1到p 連線。每條道路 ii 或者航線 ii 連線城鎮ai到bi,花費為ci。對於道路,0 ci 10,0000 ci 10,000 然而航線的花費...