zoukankan      html  css  js  c++  java
  • luogu3645 [Apio2015]雅加达的摩天大楼 (分块+dijkstra)

    我们是想跑最短路的

    我们有两种建图方式:

    1.对于每个doge i,连向B[j]==B[i]+P[i]*k ,k=..,-2,-1,0,1,2,... ,边权=|k|,这样连的复杂度是$O(Nsumlimits_{i=1}^{m}frac{1}{P[i]})$

    2.对于每个楼i,建max(P[i])个点,表示可以有一个doge经过这个楼来跳j个距离,也就是说,给P[i][j]连向P[i-j][j]和P[i+j][j],边权=1,而且还要给所有的P[i]连起来,边权是0.

    这样连的复杂度是$O(Nsumlimits_{i=1}^{m}P[i])$,其中P[i]是互不相同的(相同就不加了)

    然而都过不了

    然后我们发现,复杂度一个是乘P[i],一个是除以P[i],这就启发我们采用分块的思想,对于P[i]大于$sqrt{N}$的使用第1种建法,小于的使用第二种建法,整体的复杂度就变成$O(Nsqrt{N})$了

    然而因为玄学的常数问题,我们需要:

    1.让那个分块的边界取$min(sqrt{N},100)$(我也不知道为什么)

    2.在做最短路的时候再计算边,而不是提前都建好

    3.深吸一口氧气(必要)

    4.使用spfa而不是dijkstra(我也不知道为什么,但我还是用了dijkstra,然后就挂了...)

    (代码写一年还写得巨丑)

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define lowb(x) ((x)&(-(x)))
     4 #define REP(i,n0,n) for(i=n0;i<=n;i++)
     5 #define PER(i,n0,n) for(i=n;i>=n0;i--)
     6 #define MAX(a,b) ((a>b)?a:b)
     7 #define MIN(a,b) ((a<b)?a:b)
     8 #define CLR(a,x) memset(a,x,sizeof(a))
     9 #define rei register int
    10 using namespace std;
    11 typedef long long ll;
    12 const int maxn=30030,sqrtn=200;
    13 
    14 inline ll rd(){
    15     ll x=0;char c=getchar();int neg=1;
    16     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    17     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    18     return x*neg;
    19 }
    20 
    21 struct Node{
    22     int x,y,d;bool isp;
    23     Node (int a,int b,int c,bool s){x=a,y=b,d=c,isp=s;}
    24 }S=Node(0,0,0,0);
    25 int N,SN,M,B[maxn],P[maxn];
    26 int dis[maxn*sqrtn],poi[maxn][2],ph[maxn];
    27 bool flag[maxn*sqrtn];
    28 priority_queue<Node,vector<Node>,greater<Node> > q;
    29 
    30 bool operator > (Node a,Node b){return a.d>b.d;}
    31 inline int id(Node a){return a.isp?a.x:M+1+a.x+a.y*N;}
    32 inline void print(int x,Node a){printf("Node%d:%d %d %d %d
    ",x,a.x,a.y,a.d,a.isp);}
    33 
    34 inline int dijkstra(){
    35     memset(dis,127,sizeof(dis));
    36     dis[id(S)]=0;q.push(S);
    37     while(!q.empty()){
    38         Node p=q.top();q.pop();
    39         if(((!p.isp)&&p.x==B[1])||(p.isp&&p.x==1)) return p.d;
    40         if(flag[id(p)]) continue;
    41         
    42         if(!p.isp){
    43             for(int i=ph[p.x];i!=-1;i=poi[i][1]){
    44                 if(P[poi[i][0]]>SN){
    45                     if(dis[poi[i][0]]<=p.d) continue;
    46                     dis[poi[i][0]]=p.d;
    47                     q.push(Node(poi[i][0],0,p.d,1));
    48                 }else if(P[poi[i][0]]!=p.y){
    49                     Node x=Node(p.x,P[poi[i][0]],p.d,0);
    50                     if(dis[id(x)]<=p.d) continue;
    51                     dis[id(x)]=p.d;q.push(x);
    52                 }
    53             }
    54             if(p.y){
    55                 Node xx=Node(p.x+p.y,p.y,p.d+1,0);
    56                 if(p.x+p.y<N&&dis[id(xx)]>p.d+1){
    57                     dis[id(xx)]=p.d+1;
    58                     q.push(xx);
    59                 }xx.x=p.x-p.y;
    60                 if(p.x-p.y>=0&&dis[id(xx)]>p.d+1){
    61                     dis[id(xx)]=p.d+1;
    62                     q.push(xx);
    63                 }
    64             }
    65         }
    66         else{
    67             for(int i=B[p.x]+P[p.x],j=1;i<N;i+=P[p.x],j++){
    68                 Node a=Node(i,0,p.d+j,0);
    69                 if(dis[id(a)]>p.d+j){
    70                     dis[id(a)]=p.d+j;q.push(a);
    71                 }
    72             }
    73             for(int i=B[p.x]-P[p.x],j=1;i>=0;i-=P[p.x],j++){
    74                 Node a=Node(i,0,p.d+j,0);
    75                 if(dis[id(a)]>p.d+j){
    76                     dis[id(a)]=p.d+j;q.push(a);
    77                 }
    78             }
    79         }
    80         flag[id(p)]=1;
    81     }return -1;
    82 }
    83 
    84 int main(){
    85     //freopen(".in","r",stdin);
    86     rei i,j,k;
    87     N=rd(),M=rd();SN=min(100,(int)sqrt(N));
    88     memset(ph,-1,sizeof(ph));
    89     for(i=0;i<M;i++){
    90         B[i]=rd(),P[i]=rd();
    91         poi[i][0]=i;poi[i][1]=ph[B[i]];ph[B[i]]=i;
    92     }S=Node(B[0],0,0,0);
    93     printf("%d
    ",dijkstra());
    94     return 0;
    95 }
  • 相关阅读:
    四则运算 calc()
    如何创建width与height比例固定的元素
    eslint规则 中文备注
    使用gulp构建工具
    JavaScript 给表格排序
    【转】grunt动态生成文件名
    vim正则表达式(转)
    正则表达式30分钟入门教程(转)
    hdu 1874 Dijkstra算法
    centos7.4安装mysql
  • 原文地址:https://www.cnblogs.com/Ressed/p/9649006.html
Copyright © 2011-2022 走看看