• Luogu3350 ZJOI2016 旅行者 最短路、分治


    传送门

    题意:给出一个$N imes M$的网格图,边有边权,$Q$组询问,每组询问$(x_1,y_1)$到$(x_2,y_2)$的最短路。$N imes M leq 2 imes 10^4 , Q leq 10^5$


    BZOJ原题竟然没有数据范围

    矩形的多组询问问题考虑分治。考虑计算矩形$(x_1,y_1,x_2,y_2)$的询问,我们将较长边沿着中线劈成两半,在这些询问里面就只可能存在两种情况:①询问的两个端点在中线两边,那么路径就一定会经过中线上一点;②询问的两个端点在中线的同一边,那么有可能不会经过中线,也有可能经过中线。所以我们对中线上所有的点跑一边整个矩形的最短路,每一次跑完最短路就更新所有的询问,然后再递归进入两侧矩形回答②类型的询问。时间复杂度似乎是$O(NM imes sqrt{NM} imes log(NM))$

    在$Luogu$题解上学到的一个加速方法:从一个点的最短路转移到新的点跑最短路的时候,可以不将最短路数组赋值为极大值,而是赋值为这一个点经过上一个计算的点到达所有目标点的答案。

    然而还是在Luogu不开O2的情况下TLE

      1 // luogu-judger-enable-o2
      2 //This code is written by Itst
      3 #include<bits/stdc++.h>
      4 #define pos(i,j) ((i-1)*M+j)
      5 using namespace std;
      6 
      7 inline int read(){
      8     int a = 0;
      9     bool f = 0;
     10     char c = getchar();
     11     while(c != EOF && !isdigit(c)){
     12         if(c == '-')
     13             f = 1;
     14         c = getchar();
     15     }
     16     while(c != EOF && isdigit(c)){
     17         a = (a << 3) + (a << 1) + (c ^ '0');
     18         c = getchar();
     19     }
     20     return f ? -a : a;
     21 }
     22 
     23 const int MAXN = 100010;
     24 int cntEd , N , M , Q , minDis[MAXN] , ans[MAXN] , head[MAXN];
     25 struct Edge{
     26     int end , upEd , w;
     27 }Ed[MAXN << 2];
     28 struct query{
     29     int sx , sy , ex , ey , ind;
     30 }now[MAXN] , pot[MAXN];
     31 priority_queue < pair < int , int > > q;
     32 
     33 inline void addEd(int a , int b , int c){
     34     Ed[++cntEd].end = b;
     35     Ed[cntEd].w = c;
     36     Ed[cntEd].upEd = head[a];
     37     head[a] = cntEd;
     38 }
     39 
     40 void Dijk(int bx , int by , int lx , int ly , int rx , int ry , int l){
     41     int temp = minDis[pos(bx , by)];
     42     for(int i = lx ; i <= rx ; i++)
     43         for(int j = ly ; j <= ry ; j++)
     44             minDis[pos(i , j)] = l == 0 ? 0x3f3f3f3f : minDis[pos(i , j)] + temp;
     45     minDis[pos(bx , by)] = 0;
     46     q.push(make_pair(0 , pos(bx , by)));
     47     while(!q.empty()){
     48         pair < int , int > t = q.top();
     49         q.pop();
     50         if(minDis[t.second] != -t.first)
     51             continue;
     52         for(int i = head[t.second] ; i ; i = Ed[i].upEd)
     53             if(minDis[Ed[i].end] > minDis[t.second] + Ed[i].w){
     54                 minDis[Ed[i].end] = minDis[t.second] + Ed[i].w;
     55                 q.push(make_pair(-minDis[Ed[i].end] , Ed[i].end));
     56             }
     57     }
     58 }
     59 
     60 void solve(int lx , int ly , int rx , int ry , int ql , int qr){
     61     if(ql > qr)
     62         return;
     63     if(rx - lx > ry - ly){
     64         int mid = lx + rx >> 1;
     65         for(int i = ly ; i <= ry ; i++){
     66             Dijk(mid , i , lx , ly , rx , ry , i - ly);
     67             for(int j = ql ; j <= qr ; j++)
     68                 ans[now[j].ind] = min(ans[now[j].ind] , minDis[pos(now[j].sx , now[j].sy)] + minDis[pos(now[j].ex , now[j].ey)]);
     69         }
     70         int p1 = ql , p2 = qr;
     71         for(int i = ql ; i <= qr ; i++)
     72             if(now[i].sx < mid && now[i].ex < mid)
     73                 pot[p1++] = now[i];
     74             else
     75                 if(now[i].sx > mid && now[i].ex > mid)
     76                     pot[p2--] = now[i];
     77         memcpy(now + ql , pot + ql , sizeof(query) * (qr - ql + 1));
     78         solve(lx , ly , mid , ry , ql , p1 - 1);
     79         solve(mid + 1 , ly , rx , ry , p2 + 1 , qr);
     80     }
     81     else{
     82         int mid = ly + ry >> 1;
     83         for(int i = lx ; i <= rx ; i++){
     84             Dijk(i , mid , lx , ly , rx , ry , i - lx);
     85             for(int j = ql ; j <= qr ; j++)
     86                 ans[now[j].ind] = min(ans[now[j].ind] , minDis[pos(now[j].sx , now[j].sy)] + minDis[pos(now[j].ex , now[j].ey)]);
     87         }
     88         int p1 = ql , p2 = qr;
     89         for(int i = ql ; i <= qr ; i++)
     90             if(now[i].sy < mid && now[i].ey < mid)
     91                 pot[p1++] = now[i];
     92             else
     93                 if(now[i].sy > mid && now[i].ey > mid)
     94                     pot[p2--] = now[i];
     95         memcpy(now + ql , pot + ql , sizeof(query) * (qr - ql + 1));
     96         solve(lx , ly , rx , mid , ql , p1 - 1);
     97         solve(lx , mid + 1 , rx , ry , p2 + 1 , qr);
     98     }
     99 }
    100 
    101 int main(){
    102 #ifdef LG
    103     freopen("3350.in" , "r" , stdin);
    104     freopen("3350.out" , "w" , stdout);
    105 #endif
    106     memset(ans , 0x3f , sizeof(ans));
    107     N = read();
    108     M = read();
    109     for(int i = 1 ; i <= N ; i++)
    110         for(int j = 1 ; j < M ; j++){
    111             int t = read();
    112             addEd(pos(i , j) , pos(i , j + 1) , t);
    113             addEd(pos(i , j + 1) , pos(i , j) , t);
    114         }
    115     for(int i = 1 ; i < N ; i++)
    116         for(int j = 1 ; j <= M ; j++){
    117             int t = read();
    118             addEd(pos(i , j) , pos(i + 1 , j) , t);
    119             addEd(pos(i + 1 , j) , pos(i , j) , t);
    120         }
    121     Q = read();
    122     for(int i = 1 ; i <= Q ; i++){
    123         now[i].sx = read();
    124         now[i].sy = read();
    125         now[i].ex = read();
    126         now[i].ey = read();
    127         now[i].ind = i;
    128     }
    129     solve(1 , 1 , N , M , 1 , Q);
    130     for(int i = 1 ; i <= Q ; i++)
    131         printf("%d
    " , ans[i]);
    132     return 0;
    133 }
  • 相关阅读:
    hdu4280 Island Transport(最大流Dinic数组模拟邻接连边)
    hihoCoder1378 (最大流最小割)
    单聊语音
    Mybatis批量更新数据
    mysql 之 MRR
    Intellij IDEA 快捷键整理
    SpringBoot 整合 Swagger2 使用教程
    jdk/dubbo spi
    redis问题(待解决)
    JVM调优心得
  • 原文地址:https://www.cnblogs.com/Itst/p/9879787.html
Copyright © 2020-2023  润新知