題目鏈結
一道模板的次短路
設 d is
[x],
dist
[x
]dis[x],dist[x]
dis[x]
,dis
t[x]
分別為點 1
11 到 x
xx 的最短路和次短路長度
我們只需在跑最短路時,順帶更新一下次短路
由於每個點可以經過多次,我們只能使用 spfa
對於每條邊 [x,
y]
[x,y]
[x,y
],考慮 dis
t[y]
dist[y]
dist[y
] 的轉移:
最無腦的一種,dis
t[y]
=dis
t[x]
+w(x
,y
)dist[y]=dist[x]+w(x,y)
dist[y
]=di
st[x
]+w(
x,y)
,其中 w(x
,y
)w(x,y)
w(x,y)
為當前邊的長度
在最短路中,進行鬆弛操作後,滿足當前的 dis
[y
]dis[y]
dis[y]
小於鬆弛前的 dis
[y
]dis[y]
dis[y]
。那麼,我們就可以用鬆弛前的 dis
[y
]dis[y]
dis[y]
去更新 dis
t[y]
dist[y]
dist[y
]如果,dis
[y
] s[x] +w(x ,y )dis[y]di s[y] s[x] +w(x ,y),說明 dis [x]+ w(x, y) dis[x]+w(x,y) dis[x] +w(x ,y) 是一條次短路,所以 dis t[y] =min (dis t[y] ,dis [x]+ w(x, y) )dist[y]=min(dist[y],dis[x]+w(x,y)) dist[y ]=mi n(di st[y ],di s[x] +w(x ,y)) 。注意:這裡更新的時間是在鬆弛操作之後 關鍵**for
(int i=
0;i.size()
;++i)
else
if(dist[y]
>tmp && tmp!=dis[y]
)// 如果 dis[x]+e[x][i].len 是一條次短路
if(dist[y]
>dist[x]
+e[x]
[i].len)
}這裡說一下,題目中提到的:乙個點所直接連線的地方數量
這裡的數量並不等於這個節點的度數(連邊數),因為兩個節點之間可能有多條邊。這才是正確的開啟方式:
for
(int x=
1;x<=n;
++x)
memset
(vis,0,
sizeof
(vis));
}
完整**
#include
#include
#include
#include
#include
#include
using
namespace std;
const
int maxn=
10010
,inf=
0x3f3f3f3f
;struct edge};
int dis[maxn]
,dist[maxn]
,d[maxn]
;bool vis[maxn]
;int n,m,k;
vector e[maxn]
;void
spfa()
else
if(dist[y]
>tmp && tmp!=dis[y])if
(dist[y]
>dist[x]
+e[x]
[i].len)}}
}int
main()
for(
int x=
1;x<=n;
++x)
memset
(vis,0,
sizeof
(vis));
}spfa()
;if(dist[n]
==inf)
puts
("-1");
else
printf
("%d\n"
,dist[n]);
return0;
}
洛谷P1373小a和uim大逃離題解
這個題好坑啊,首先是他會卡空間,然後我們就只能把一種比較好理解的狀態給捨棄,因為空間開不下,然而採用一種難理解的狀態就是 dp i j l 0 1 表示 i j 位置,兩者的差為 l 當前由誰來吸收的方案數。然後我們就可以推出狀態轉移方程,此狀態轉移方程很好寫,主要就是狀態非常難想,因此我們如果狀態...
洛谷 P1095 守望者的逃離題解
解題思路 首先dp的套路就是先找狀態,這題也找不出其他的狀態了,只有時間乙個,所以用f i 表示時刻i能走多遠。仔細一想實際上決策只有跑 閃現 停三種決策 然而閃現的耗藍要和跑步一同計算十分麻煩。於是把它們分開算 先算閃現的,有以下框架 for i in range 1,t 如果藍量夠 閃現,耗藍 ...
洛谷2758 編輯距離 題解
字串編輯距離板子題,留乙個底,方便日後。設a和b是兩個字串。我們要用最少的字元操作次數,將字串a轉換為字串b。這裡所說的字元操作共有三種 1 刪除乙個字元 2 插入乙個字元 3 將乙個字元改為另乙個字元 皆為小寫字母!題解網上搜一大堆 其實光看 也都能看懂這道題。include include in...