題解 P3831 SHOI2012 回家的路

2022-09-23 21:30:28 字數 1392 閱讀 5895

什麼叫分層圖最短路,我不會/kk

感覺自己做法和其他題解不大一樣所以過來發篇題解了。

未刻意卡常拿下最優解

就是說給你乙個 \(n \times n\) 的網格圖和 \(m\) 個可換乘點,然後你只能在同一行或同一列(如果在行上移動,就不能在列上移動;反之同理)上移動,除非這個點是可以換乘的。每次走一格花費 \(2\) 費,換乘花費 \(1\) 費,求從 \((sx,sy)\) 到 \((fx,fy)\) 的最小費用。

其中:\(n \leqslant 20000,m \leqslant 100000\)

可以發現如果對於每個格點都儲存資訊是不可行的,我們考慮優化空間:發現我們的路徑實際上就是一直衝,然後只有在部分換乘點轉彎,所以我們可以把換乘點聯絡起來,在換乘點之間跑最短路。

那麼具體怎麼做呢,我們考慮對於每行和每列開領接表,儲存這一行或這一列上,存在的換乘點的編號。然後可以把起始點也看做換乘點。然後跑最短路的時候就直接通過兩點的距離\(\times 2 + 1\) 來轉移最短路距離(因為我們去換乘點便是為了轉彎),最後輸出 \(dis[\) 終點編號 \(]-1\)即可(\(-1\) 是為了把在終點轉彎的費用減掉)。最後注意陣列大小別開錯就行了。(我因為這個wa了一發)

那麼看**吧!

#includeusing namespace std;

inline int read()

const int inf=1e9;

const int n=20000+3;

const int m=100002+3;

struct nodep[m];

int n,m;

int sx,sy,fx,fy;

queueq;

int dis[m];

bool inq[m];

vectorh[n],l[n];

inline void spfa()

dis[1]=0;

while(!q.empty())

}} for(int i=0;i=dis[u]+val)

}} }

}int main()

sx=read();sy=read();fx=read();fy=read();

h[sx].push_back(1);l[sy].push_back(1);

h[fx].push_back(m+2);l[fy].push_back(m+2);//把起始點當做換乘點

p[1]=;p[m+2]=;

spfa();

if(dis[m+2]!=inf) printf("%d\n",dis[m+2]-1);//除去多餘的最後一次轉彎費用

else printf("-1\n");//無法到達輸-1

return 0;

}

似乎比其他題解的做法簡單一些?

P3831 SHOI2012 回家的路 題解

題目傳送門 解法 1 每兩個點都連邊,跑裸的最短路。顯然,n 和 m 非常大,暴力連邊會 tle 和 mle。解法 2 正解 首先,對答案產生貢獻的只有換乘站,所以我們只用連兩種邊 乙個換乘站看作 2 個節點,連邊,邊權為 1 站內換乘 將 x 相等的換乘站相連,y 相等的換乘站相連。其中,起點和終...

題解 SHOI2012 隨機樹

題目傳送門 不難看出,答案就是 1 sum 2 i 1 這個問真的很仙。可 bu 以 neng 想到,我們可以設 f 表示有 i 個葉子時深度 ge j 的概率,可以得到轉移式 f frac sum f f f times f 可以直接除以 i 1 是因為可以證明把兩顆子樹合併,只要總大小相同,那麼...

洛谷 P3833 SHOI2012 魔法樹

shoi2012 d2t3 harry potter 新學了一種魔法 可以讓改變樹上的果子個數。滿心歡喜的他找到了乙個巨大的果樹,來試驗他的新法術。這棵果樹共有n個節點,其中節點0是根節點,每個節點u的父親記為fa u 保證有fa u u。初始時,這棵果樹上的果子都被 dumbledore 用魔法清...