最短路計數 spfa

2021-08-06 00:15:12 字數 2217 閱讀 4386

題目描述

給出乙個n個頂點m條邊的無向無權圖,頂點編號為1~n。問從頂點1開始,到其他每個點的最短路有幾條。

輸入輸出格式

輸入格式:

輸入第一行包含2個正整數n,m,為圖的頂點數與邊數。

接下來m行,每行兩個正整數x, y,表示有一條頂點x連向頂點y的邊,請注意可能有自環與重邊。

輸出格式:

輸出包括n行,每行乙個非負整數,第i行輸出從頂點1到頂點i有多少條不同的最短路,由於答案有可能會很大,你只需要輸出mod 100003後的結果即可。如果無法到達頂點i則輸出0。

輸入輸出樣例

輸入樣例#1:

5 7

1 2

1 3

2 4

3 4

2 3

4 5

4 5

輸出樣例#1:

1 1

1 2

4 說明

1到5的最短路有4條,分別為2條1-2-4-5和2條1-3-4-5(由於4-5的邊有2條)。

對於20%的資料,n ≤ 100;

對於60%的資料,n ≤ 1000;

對於100%的資料,n<=1000000,m<=2000000。

分析 spfa+佇列優化:

ans[i]表示有多少條1到i點的最短路。

雙向圖,要把2個相連的點正反方向都儲存。

做乙個spfa,如果dis[s[i]]+1小於當前的dis[t[i]]就替換,並且ans[t[i]]就等於ans[s[i]]的數量,如果等於把ans[t[i]]跟ans[s[i]]合併。

最後輸出就好了,不過要注意取模。

程式:

var

next,ls,s,t,w,p:array[0..500001]of longint;

d,a:array[0..1000001]of longint;

v:array[0..1000001]of boolean;

n,m,q,i,j,g:longint;

procedure

spfa;

varhead,tail,i:longint;

begin

head:=0;tail:=1;

d[1]:=0;

a[1]:=1;

v[1]:=true;

p[1]:=1;

while headdo

begin

inc(head);

i:=ls[p[head]];

while i>0

dobegin

if d[s[i]]+1=d[t[i]] then a[t[i]]:=(a[t[i]]+a[s[i]]) mod

100003;

if d[s[i]]+1

then

begin

d[t[i]]:=d[s[i]]+1;

if v[t[i]]=false

then

begin

v[t[i]]:=true;

inc(tail);

p[tail]:=t[i];

end;

a[t[i]]:=a[s[i]];

end;

i:=next[i];

end;

v[p[head]]:=false;

end;

end;

begin

fillchar(next,sizeof(next),0);

fillchar(ls,sizeof(ls),0);

readln(n,g);

i:=0;

for j:=1

to g do

begin

inc(i);

readln(s[i],t[i]);

next[i]:=ls[s[i]];

ls[s[i]]:=i;

inc(i);

s[i]:=t[i-1];t[i]:=s[i-1];

next[i]:=ls[s[i]];

ls[s[i]]:=i;

end;

for i:=1

to n do

begin

d[i]:=maxlongint;

v[i]:=false;

end;

spfa;

for i:=1

to n do

writeln(a[i]);

end.

洛谷最短路計數SPFA

給出乙個n個頂點m條邊的無向無權圖,頂點編號為1 n。問從頂點1開始,到其他每個點的最短路有幾條。輸入格式 輸入第一行包含2個正整數n,m,為圖的頂點數與邊數。接下來m行,每行兩個正整數x,y,表示有一條頂點x連向頂點y的邊,請注意可能有自環與重邊。輸出格式 輸出包括n行,每行乙個非負整數,第i行輸...

洛谷 P1144 最短路計數(最短路 SPFA)

傳送門 資料範圍看起來好像很嚇人,但我還是水過去了嘻嘻 先跑一遍spfa確定最短路長度,然後用記憶化搜尋累加答案 點1到點1的答案為1,然後遞迴搜尋,如果下乙個點在最短路徑上,我就把我的答案加上它的答案 code include include include struct nodea 400001...

最短路 spfa (一)

最短路 spfa 首先建立起始點a到其餘各點的 最短路徑 首先源點a入隊,當佇列非空時 隊首元素a 出隊,對以a為起始點的所有邊的終點依次進行鬆弛操作 此處有b,c,d三個點 此時路徑 狀態為 在鬆弛時三個點的最短路徑估值變小了,而這些點佇列中都沒有出現,這些點 需要入隊,此時,佇列中新入隊了三個結...