最短路 拓撲排序 dp NOIP 2017 逛公園

2021-08-29 07:08:18 字數 3320 閱讀 4680

讓我們一起來%forever_shi神犇

題意:給你乙個n

nn個點m

mm條邊的有向帶權圖,設1

11號點到n

nn號點的最短路是dis

disdi

s,給你乙個k(k

<=50

)k(k<=50)

k(k<=5

0),求所有1

11到n

nn的路徑中長度不超過dis

+k

dis+k

dis+

k的數量。

題解:顯然我們要先處理出最短路,如果k=0

k=0k=

0,就是最短路計數了。要做計數,我們不難想到要在圖上dpdp

dp。我們發現只要有乙個邊權全部是0

00的環,那麼我們的滿足題意的路徑就會有無數條,因為可以在環裡轉任意多圈之後再出來。那麼我們要判斷是否有無窮多解就是去找有沒有全部是0

00的環。

我們可以先處理出乙個最短路圖,最短路圖的含義是由所有dis

[x]+

w[x]

[y]=

dis[

y]

dis[x]+w[x][y]=dis[y]

dis[x]

+w[x

][y]

=dis

[y]的邊連成的圖,最短路圖的乙個性質:如果邊權都是正數,那麼最短路圖是乙個dag。dag是可以拓撲排序的,如果最後每個點入度都是0

00,就不存在權值全是0

00的環,否則就是有權值全是0

00的環,因為權值是0

00的邊一定不會讓兩點之間的最短路變長,所以其就一定會在最短路圖上,而形成環的話是沒法有其中某乙個點的入度是0

00,因此判斷拓撲排序後的入度即可。

對圖拓撲排序後根據圖的拓撲序在dag上dpdp

dp也是乙個經典套路,這裡我們就會採用這個套路。我們設dp[

i][j

]dp[i][j]

dp[i][

j]表示對於點i

ii比dis

[i

]dis[i]

dis[i]

大j

jj的路徑數,那麼對於路徑x

−>

yx−>y

x−>

y,狀態轉移方程即為:dp[

y][j

+w(x

,y)−

(dis

[y]−

dis[

x])]

+=dp

[x][

j]

dp[y][j+w(x,y)−(dis[y]−dis[x])]+=dp[x][j]

dp[y][

j+w(

x,y)

−(di

s[y]

−dis

[x])

]+=d

p[x]

[j]。

那麼我們列舉j

jj,然後按照拓撲序列舉x

xx,再列舉從x

xx出發的所有邊,進行dpdp

dp。注意外層是列舉j

jj,因為在dpdp

dp的過程中如果外層列舉x

xx的話dag上是沒有環的,但是這裡的邊是列舉原圖的邊,所以可能之後會有環再回到x

xx,得到答案就是錯誤的了。還有就是這個dpdp

dp看似列舉的層數很多,但是其實複雜度並不高,因為所有邊都只會被列舉到一次,所有點都只會被列舉k+1

(0到k

)k+1(0到k)

k+1(0到

k)次,所以總的複雜度是o(n

∗k

)o(n∗k)

o(n∗k)

的。最後答案就是∑i=

0kdp

[n][

i]

了\sum^k_dp[n][i]了

∑i=0k​

dp[n

][i]

了 (吸氧苟過去qaq)

#include

#define ll long long

#define rint register int

using

namespace std;

const

int maxn=

201000

;struct node

e[maxn]

,a[maxn]

;int head[maxn]

,head1[maxn]

,num,num1,i;

int dis[maxn]

,n,m,t,k,p,rd[maxn]

,numm[maxn]

;int que[maxn]

,ji,u,v,d;

ll dp[

200200][

55],ans;

bool book[maxn]

;priority_queueint,

int>

> q;

intread()

while

(c>=

'0'&&c<=

'9')

return x*y;

}void

add(

int from,

int to,

int dis)

void

add1

(int from,

int to,

int dis)

void

dij(

int s)}}

}void

topsort()

h++;}

}int

main()

dij(1)

;for

(rint i=

1;i<=num;

++i)

}topsort()

;for

(rint i=

1;i<=n;

++i)

if(rd[i])if

(flag)

dp[1]

[0]=

1;for(rint k=

0;k<=k;

++k)

for(rint i=

1;i<=n;

++i)

}for

(rint i=

0;i<=k;

++i)

ans=

(ans%p+dp[n]

[i]%p)

%p;printf

("%d\n"

,ans);}

return0;

}

離散化 拓撲排序 最短路堆優化

資料範圍太大,自身無法作為陣列的下標儲存對應的屬性,當資料至於他們之間的相對大小有關,而與具體值無關時,則可以進行離散化。做法 不改變資料相對大小的前提下,對資料進行縮小 struct node a 100001 從小到大排序 b 100001 for i 1 i n i b a i order i...

CSP模擬賽 益智遊戲(最短路 拓撲排序)

題目描述 小p和小r在玩一款益智遊戲。遊戲在乙個正權有向圖上進行。小p 控制的角色要從a 點走最短路到b 點,小r 控制的角色要從c 點走最短路到d 點。乙個玩家每回合可以有兩種選擇,移動到乙個相鄰節點或者休息一回合。假如在某一時刻,小p 和小r 在相同的節點上,那麼可以得到一次特殊獎勵,但是在每 ...

道路與航線(最短路 縮點 拓撲排序)

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