洛谷P1144 最短路計數 及其引申思考

2022-03-04 22:31:05 字數 1922 閱讀 6707

圖論題目練得比較少,發一道spfa的板子題目~

給出乙個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 21 3

2 43 4

2 34 5

4 5

輸出樣例#1:

111

24

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只能記錄單點到其它點的一條最短路,這題又要輸出最短路個數取模,讓人琢磨不透。so,默默的看看標籤吧,普及+提高,嗯貌似不是很難,看下解題標籤:spfa,bfs,圖論,最短路。ok,果然還是要用到spfa,我們關鍵是要想到如何去處理重邊和最短路計數。於是乎,我們先寫一下spfa的模板,然後再來思考,不難發現:邊權都為1,對於重邊在spfa中會進行多次才到下乙個點,所以路徑數會記錄下來,而且在spfa的鬆弛操作中由於邊權均為1所以每個點只會鬆弛一次,於是乎在跑spfa時我們只需判斷dis[v]==dis[u]+1是否成立,若成立,對於ans就加上到u點的邊的條數再取模。這樣這道題就完美的解決了。

1 #include2

#pragma gcc optimize(2)

3using

namespace

std;

4#define ll long long

5#define il inline

6#define mod 100003

7#define n 1000005

8#define inf 233333333

9int

n,m,h[n],dis[n],cnt,ans[n];

10bool

vis[n];

11 queueq;

12 il int

gi()

1320

struct

edgee[n<<2

];23 il void add(int u,int v)

24 il void spfa(int

s)25

41else

if(dis[v]==dis[u]+1)ans[v]=(ans[v]+ans[u])%mod;42}

43}44}

45int

main()

4654 spfa(1

);55

for(int i=1;i<=n;i++)printf("

%d\n

",ans[i]);

56return0;

57 }

由這道題我們想到,如果對與任意乙個有向無環且帶權的圖,需要輸出規定原點到其它點的最短路徑條數,這樣應該怎麼去做呢?

我們可以先跑一遍spfa,再進行dag+dp(或者記憶化搜尋),也可以直接兩遍spfa跑過(yzk大佬告訴我的方法,仔細想想思路都差不多,原理還是dp),於是乎,論dp的重要性,當然也可以看出spfa的應用有多廣泛。。。

推廣題:poj3463(解題報告)

洛谷 P1144 最短路計數

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

洛谷 P1144 最短路計數

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

洛谷 P1144 最短路計數

給出乙個nn個頂點mm條邊的無向無權圖,頂點編號為1 n1 n。問從頂點11開始,到其他每個點的最短路有幾條。第一行包含22個正整數n,mn,m,為圖的頂點數與邊數。接下來mm行,每行22個正整數x,yx,y,表示有一條頂點xx連向頂點yy的邊,請注意可能有自環與重邊。共nn行,每行乙個非負整數,第...