Returning Home(建圖、最短路)
題意
給定一個 n ∗ n n*n n∗n的網格,在這個網格中給出兩個座標,分別作為起點和終點。並且在圖中存在 m m m個傳送陣,傳送陣的座標已知。從起點開始向終點走,相鄰兩個位置之間花費一個單位,如果走到與某個傳送陣同行或者同列,那麼可以不耗花費的傳送到那個傳送陣的位置。問從起點到終點,最少花費多少單位。
資料範圍
1
≤
n
≤
1
0
9
1 \leq n \leq 10^9
1≤n≤109
0
≤
m
≤
1
0
5
0 \leq m \leq 10^5
0≤m≤105
思路
如果傳送陣直接建一個完全圖,那麼顯然會爆空間和時間,因此需要考慮更簡潔的建圖方式。
首先我們可以考慮到,兩個傳送陣之間的距離為
m
i
n
(
x
2
−
x
1
,
y
2
−
y
1
)
min(x_2 - x_1, y_2 - y_1)
min(x2−x1,y2−y1),這就等價於兩個傳送陣在同一行或者同一列上。因此,我們可以對傳送陣的橫座標排序,相鄰兩個連起來;再對傳送陣的縱座標排序,相鄰兩個連起來。因為要求的是最短路,所以兩點之間出現重邊也沒關係。
最後,將起點作為
0
0
0號點,終點作為
m
+
1
m+1
m+1號點,起點向每一個傳送陣連一條邊,終點向每個傳送陣連一條邊,起點和終點之間再連一條邊。值得注意的是,起點到傳送陣的距離計算方式和傳送陣到終點的距離計算方式是不同的,因為一個可以傳送,另一個不能傳送。
這樣圖就建好了,然後跑一個Dijkstra演算法就完成了。
程式碼
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pli;
typedef pair<int,ll> pil;
const int N = 100010, M = 10 * N;
const ll inf = 1e18;
int sz,n,S,T;
int h[N], e[M], ne[M], idx;
ll w[M];
ll xx[N], yy[N];
ll dist[N];
bool st[N];
pli x_id[N], y_id[N];
void add(int a,int b,ll c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}
void dijkstra()
{
for(int i=0;i<=n+1;i++) dist[i] = inf;
memset(st,0,sizeof(st));
dist[0] = 0;
priority_queue<pli,vector<pli>,greater<pli> > heap;
heap.push({dist[0],0});
while(heap.size()){
auto t = heap.top();
heap.pop();
int ver = t.second;
ll distance = t.first;
if(st[ver]) continue;
st[ver] = true;
for(int i=h[ver];~i;i=ne[i]){
int j = e[i];
if(dist[j]>distance+w[i]){
dist[j] = distance + w[i];
heap.push({dist[j],j});
}
}
}
}
int main()
{
cin >> sz >> n;
memset(h,-1,sizeof(h));
ll sx,sy,fx,fy;
cin >> sx >> sy >> fx >> fy;
ll dd = abs(sx - fx) + abs(sy - fy);
add(0,n+1,dd), add(n+1,0,dd);
for(int i=1;i<=n;i++){
cin >> xx[i] >> yy[i];
x_id[i] = {xx[i],i}, y_id[i] = {yy[i],i};
}
for(int i=1;i<=n;i++){
ll d = min(abs(sx-xx[i]),abs(sy-yy[i]));
add(0,i,d), add(i,0,d);
}
for(int i=1;i<=n;i++){
ll d = abs(fx-xx[i]) + abs(fy-yy[i]);
add(n+1,i,d), add(i,n+1,d);
}
sort(x_id+1,x_id+n+1);
sort(y_id+1,y_id+n+1);
for(int i=1;i<n;i++){
int id1 = x_id[i].second, id2 = x_id[i+1].second;
ll d = abs(x_id[i].first - x_id[i+1].first);
add(id1,id2,d), add(id2,id1,d);
}
for(int i=1;i<n;i++){
int id1 = y_id[i].second, id2 = y_id[i+1].second;
ll d = abs(y_id[i].first - y_id[i+1].first);
add(id1,id2,d), add(id2,id1,d);
}
dijkstra();
cout << dist[n+1] << endl;
return 0;
}
相關文章
- CodeForces_1422D Returning Home(最短路)
- 最短路:求最長最短路
- 最短路 || 最長路 || 次短路
- POJ2387 Til the Cows Come Home【最短路 Dijkstra演算法】演算法
- 最短路圖論圖論
- 圖 - 最短路徑
- 分層圖最短路
- 圖論-Dijkstra最短路圖論
- 分層圖求最短路
- 圖論 最短路總結圖論
- 圖的最短路徑(Dijkstra | Floyd)
- 【原創】MySQL 返回更新值(RETURNING)MySql
- DS圖—圖的最短路徑(不含程式碼框架)框架
- 圖論最短路演算法筆記圖論演算法筆記
- 圖的最短路徑演算法彙總演算法
- AdGuard Home
- KunlunDB功能之insert/update/delete...returning語句delete
- 圖論最短路徑問題與matlab實現圖論Matlab
- 圖的最短路徑問題 詳細分解版
- bellman-ford 單源最短路問題 圖解圖解
- 建圖
- 最短路
- 次短路
- Laravel7.0 Route::get ()->name ('home') route ('home') 報錯Laravel
- [vue-router] Duplicate named routes definition: { name: "home", path: "/home" }Vue
- 最大值(最短路+最短路計數)
- 初始化home
- 2024_4_22 路徑花費為最長$k$條邊之和最短路
- 構建最簡單陣列陣列
- 最短路-Floyd
- BZOJ2763: [JLOI2011]飛行路線(分層圖 最短路)
- 演算法與資料結構之-圖的最短路徑演算法資料結構
- 圖論系列之「廣度優先遍歷及無權圖的最短路徑(ShortPath)」圖論
- Python 圖_系列之基於<連結表>實現無向圖最短路徑搜尋Python
- AdGuard Home使用體驗
- spark_home的配置Spark
- 最短路專項
- 擴點最短路