題目描述
農夫約翰正在乙個新的銷售區域對他的牛奶銷售方案進行調查。輸入格式他想把牛奶送到t個城鎮,編號為1~t。
這些城鎮之間通過r條道路 (編號為1到r) 和p條航線 (編號為1到p) 連線。
每條道路 i 或者航線 i 連線城鎮ai到bi,花費為ci。
對於道路,0≤ci≤10,000;然而航線的花費很神奇,花費ci可能是負數(−10,000≤ci≤10,000)。
道路是雙向的,可以從ai到bi,也可以從bi到ai,花費都是ci。
然而航線與之不同,只可以從ai到bi。
事實上,由於最近恐怖主義太囂張,為了社會和諧,出台了一些政策:保證如果有一條航線可以從ai到bi,那麼保證不可能通過一些道路和航線從bi回到ai。
由於約翰的奶牛世界公認十分給力,他需要運送奶牛到每乙個城鎮。
他想找到從傳送中心城鎮s把奶牛送到每個城鎮的最便宜的方案。
第一行包含四個整數t,r,p,s。輸出格式接下來r行,每行包含三個整數(表示乙個道路)ai,bi,ci。
接下來p行,每行包含三個整數(表示一條航線)ai,bi,ci。
第1…t行:第i行輸出從s到達城鎮i的最小花費,如果不存在,則輸出「no path」。資料範圍
1≤t≤25000,1≤r,p≤50000,
1≤ai,bi,s≤t,
輸入樣例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 path50
-95-100
看完這道題之後第乙個想到的應該是用spfa演算法來直接求最短路,但是這道題會卡spfa,因此我們需要考慮要如何用dijkstra演算法來解決這道題。
因為這道題目存在負權邊,因此我們不能直接用dijkstra演算法來解決這道題。因為題目保證:如果有一條航線可以從ai到bi,那麼保證不可能通過一些道路和航線從bi回到ai。因此說明航線之間是無環的且航線不可能和道路是重邊。
因此,如果我們將所有的道路連通塊縮成乙個點,那麼這個圖就變成了乙個dag。此時我們就可以對這個圖進行拓撲排序了,然後再根據拓撲序進行遞推,最終就可以求出到達每個點的最短路徑。
(注:每個縮點內部的最短路我們可以直接用dijkstra算出)
這個題的思路相對來說不算太難,這道題的**實現也是乙個難點。
一下是yxc大佬給出的實現流程圖:
**如下
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define ull unsigned long long
#define pii pair
#define x first
#define y second
using
namespace std;
const
int n=
5e4+
5,inf=
0x3f3f3f3f
;int h[n]
,e[n*3]
,w[n*3]
,ne[n*3]
,idx;
int dist[n]
;bool st[n]
;int scc[n]
,in[n]
,cnt;
//scc 記錄每個點屬於那個連通塊,in統計入度,cnt 記錄連通塊數量
vector<
int> block[n]
;//記錄每個連通塊中含有那些點
queue<
int> q;
void
add(
int a,
int b,
int c)
//加邊函式
void
dfs(
int u,
int cnt)
}void
dijkstra
(int s));
//將該連通塊中的點全部放入堆中
while
(heap.
size()
));}
}}}void
topsort
(int s,
int n)
}int
main()
for(
int i=
1;i<=n;i++
)//dfs找出所有連通塊if(
!scc[i]
)dfs
(i,++cnt)
;while
(p--
)//輸入水路
topsort
(s,n)
;//求其拓撲序,並計算最短路
for(
int i=
1;i<=n;i++)if
(dist[i]
>inf/2)
puts
("no path");
else
printf
("%d\n"
,dist[i]);
return0;
}
bzoj 2200 道路與航線 最短路高階
time limit 10 sec memory limit 259 mb submit 528 solved 173 submit status discuss farmer john正在乙個新的銷售區域對他的牛奶銷售方案進行調查。他想把牛奶送到t個城鎮 1 t 25,000 編號為1t。這些城鎮...
bzoj 1179 縮點 最短路
題意 中文題面 解題思路 因為他能重複走且邊權都正的,那麼肯定乙個環的是必須走完的,所以先縮點,在重新建乙個圖跑最長路 include include include include include include includeusing namespace std const int inf 0...
POJ2762 tarjan縮點 拓撲排序
有向圖n 1000 m 6000,如果圖中任意兩點u,v 均有u可達v或v可達u,輸出yes,否則輸出no 嘛,強連通分量內的點肯定互相可達 對於縮點之後的dag,怎麼判呢?如果一開始就有多個入度為0的點,那麼就是no 交一發wa了 這時候就要想反例了 發現有一種情況也是no 比如1 2 1 3,2...