日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[ZJOI2016]旅行者(网格图分治最短路)

發布時間:2023/12/3 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [ZJOI2016]旅行者(网格图分治最短路) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

problem

luogu-P3350

solution

據說,網格圖最短路用分治是一個人人皆知的套路。對不起我不是人

類比整體二分的算法流程。

考慮在一個 (xl,yl)?(yl,yr)(xl,yl)-(yl,yr)(xl,yl)?(yl,yr) 矩陣內處理 [ql,qr][ql,qr][ql,qr] 的詢問。

以矩陣的中界線 mid\text{mid}mid 將矩陣劃成兩半,顯然哪一維更長劃哪一維。

以中界線上的每一個點為起點跑一遍最短路,然后更新所有需要跨過這條線的詢問的答案,相當于是強制路線必須經過該點。

如果不需要跨過這條線,即詢問的起終點均在線的某一側,就分成 l,rl,rl,r 兩個部分,繼續分治下去。

時間復雜度好像都說是 O(NNlog?N)O(N\sqrt{N}\log N)O(NN?logN)

具體見代碼即可明白。

code

#include <bits/stdc++.h> using namespace std; #define maxn 20005 #define maxq 100005 #define Pair pair < int, int > struct node { int u, v, id; }q[maxq], l[maxq], r[maxq]; vector < Pair > G[maxn]; priority_queue < Pair, vector < Pair >, greater < Pair > > que; int x[maxn], y[maxn], dis[maxn], ans[maxq]; int n, m, Q;int id( int i, int j ) { return (i - 1) * m + j; }void dijkstra( int s, int xl, int xr, int yl, int yr ) {for( int i = xl;i <= xr;i ++ )for( int j = yl;j <= yr;j ++ )dis[id(i, j)] = 0x7f7f7f7f;que.push( make_pair( dis[s] = 0, s ) );while( ! que.empty() ) {int u = que.top().second, w = que.top().first;que.pop();if( dis[u] ^ w ) continue;for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i].first; w = G[u][i].second;if( x[v] < xl or x[v] > xr or y[v] < yl or y[v] > yr ) continue;if( dis[v] > dis[u] + w )que.push( make_pair( dis[v] = dis[u] + w, v ) );}} }void solve( int ql, int qr, int xl, int xr, int yl, int yr ) {if( ql > qr or xl > xr or yl > yr ) return;int cntl = 0, cntr = 0;if( xr - xl >= yr - yl ) {int mid = xr + xl >> 1;for( int i = yl;i <= yr;i ++ ) {dijkstra( id(mid, i), xl, xr, yl, yr );for( int j = ql;j <= qr;j ++ )ans[q[j].id] = min( ans[q[j].id], dis[q[j].u] + dis[q[j].v] );}for( int i = ql;i <= qr;i ++ ) {if( x[q[i].u] < mid and x[q[i].v] < mid ) l[++ cntl] = q[i];if( x[q[i].u] > mid and x[q[i].v] > mid ) r[++ cntr] = q[i];}for( int i = 1;i <= cntl;i ++ ) q[ql + i - 1] = l[i];for( int i = 1;i <= cntr;i ++ ) q[ql + cntl + i - 1] = r[i];solve( ql, ql + cntl - 1, xl, mid - 1, yl, yr );solve( ql + cntl, ql + cntl + cntr - 1, mid + 1, xr, yl, yr );}else {int mid = yr + yl >> 1;for( int i = xl;i <= xr;i ++ ) {dijkstra( id(i, mid), xl, xr, yl, yr );for( int j = ql;j <= qr;j ++ )ans[q[j].id] = min( ans[q[j].id], dis[q[j].u] + dis[q[j].v] );}for( int i = ql;i <= qr;i ++ ) {if( y[q[i].u] < mid and y[q[i].v] < mid ) l[++ cntl] = q[i];if( y[q[i].u] > mid and y[q[i].v] > mid ) r[++ cntr] = q[i];}for( int i = 1;i <= cntl;i ++ ) q[ql + i - 1] = l[i];for( int i = 1;i <= cntr;i ++ ) q[ql + cntl + i - 1] = r[i];solve( ql, ql + cntl - 1, xl, xr, yl, mid - 1 );solve( ql + cntl, ql + cntl + cntr - 1, xl, xr, mid + 1, yr );} }int main() {scanf( "%d %d", &n, &m );for( int i = 1;i <= n;i ++ )for( int j = 1, x;j < m;j ++ ) {scanf( "%d", &x );G[id(i, j)].push_back( make_pair( id(i, j + 1), x ) );G[id(i, j + 1)].push_back( make_pair( id(i, j), x ) );}for( int i = 1;i < n;i ++ )for( int j = 1, x;j <= m;j ++ ) {scanf( "%d", &x );G[id(i, j)].push_back( make_pair( id(i + 1, j), x ) );G[id(i + 1, j)].push_back( make_pair( id(i, j), x ) );}for( int i = 1;i <= n;i ++ )for( int j = 1;j <= m;j ++ )x[id(i, j)] = i, y[id(i, j)] = j;scanf( "%d", &Q );for( int i = 1, a1, b1, a2, b2;i <= Q;i ++ ) {scanf( "%d %d %d %d", &a1, &b1, &a2, &b2 );q[i] = (node){ id(a1, b1), id(a2, b2) }, q[i].id = i;}memset( ans, 0x7f, sizeof( ans ) );solve( 1, Q, 1, n, 1, m );for( int i = 1;i <= Q;i ++ ) printf( "%d\n", ans[i] );return 0; }

總結

以上是生活随笔為你收集整理的[ZJOI2016]旅行者(网格图分治最短路)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。