道路和航線

2022-08-16 13:33:14 字數 1682 閱讀 8767

題目描述

一張圖,有由t個節點,r條雙向邊和p條單向邊組成,每條邊有邊權且可能存在負權,求能否從s到達每個節點並且輸出最小花費。

思路首先第一想法,把這張圖建出來,在跑一遍spfa即可,然而它顯然被卡了,不過似乎可以用雙端佇列優化水過去。

接下就是正解。我們考慮對於所有的道路,都是正權,我們可以用dijkstra做,而對於航線,不存在環。因此,如果我們將道路相連的連通圖縮點之後,得到必定是dag,而dag顯然可以用拓撲排序更新最短路。

所以我們只需要先把雙向邊的圖建出來,跑一遍tarjan縮點,再進行toposort,每次更新時把連通塊中所有節點都加入dijkstra的優先佇列中,對於每個點進行更新dis陣列。在進行dijkstra時把單向邊也更新一遍即可。

**

#includeusing

namespace

std;

const

int n=250020,m=1e5+10

;const

int inf=0x3f3f3f3f

;int

head[n],tot,to[m],nxt[m],w[m];

void add_edge(int x,int y,int z) //

雙向邊建圖

intdfn[n],top,idx,st[n],low[n];

intco[n],col;

vector

g[n];

bool

vis[n];

void tarjan(int u) //

tarjan縮點

else low[u]=min(low[u],dfn[v]);

}if(low[u]==dfn[u])

top--;

}}int

dis[n];

priority_queue

int,int> >q;

queue

que;

int fir[n],cnt,nex[m],ed[m],c[m],in

[n];

void add(int x,int y,int z) //

單向邊建圖

void

dijkstra()

}for(int i=fir[u];i;i=nex[i]) //

更新單向邊

}}void toposort(int

s) dijkstra();

}}int

read()

while(ch>='

0'&&ch<='9')

return res*w;

}void write(int

x)

if(x>9)write(x/10

); putchar(x%10^48);}

void writeln(int

x)int

main()

for(int i=1;i<=t;i++)

if(!dfn[i])tarjan(i);

for(int i=1;i<=p;i++)

toposort(s);

for(int i=1;i<=t;i++)

if(dis[i]==inf)puts("

no path");

else

writeln(dis[i]);

}

道路和航線

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

道路和航線 題解

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

道路與航線

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