• 洛谷P3645 [APIO2015]雅加达的摩天楼(最短路+分块)


    传送门

    这最短路的建图怎么和网络流一样玄学……

    一个最朴素的想法是从每一个点向它能到达的所有点连边,边权为跳的次数,然后跑最短路(然而边数是$O(n^2)$除非自创复杂度比spfa和dijkstra还有优秀的做法否则根本过不了)

    那么考虑一下分块

    把每一座建筑拆成$O(sqrt{n})$层,第$i$层代表在这一层只能每一步跳$i$个建筑,然后这一层每一个建筑向它能到达的点连双向边

    然后每一层每一个建筑向底层连边,代表如果这里有其他狗就可以更换跳的步数

    然后考虑每一只狗,如果它每一步跳的步数小于$sqrt{n}$,那么直接把它向对应建筑对应层数的点连边

    如果大于$sqrt{n}$,直接暴力向它能到达的点连边,那么连边的条数不会超过$O(logn)$

    所以实际的边数不会超过$O(nlogn)$,那么就跑一个最短路就好了

    然而似乎spfa诈尸……这题卡dijkstra只能用spfa

    然而数据很诡异块的大小得调成$min(sqrt{n},100)$

    差不多就这样

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<queue>
     6 #include<cmath>
     7 #define id(i,k) ((n*k)+i)
     8 using namespace std;
     9 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    10 char buf[1<<21],*p1=buf,*p2=buf;
    11 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    12 inline int read(){
    13     #define num ch-'0'
    14     char ch;bool flag=0;int res;
    15     while(!isdigit(ch=getc()))
    16     (ch=='-')&&(flag=true);
    17     for(res=num;isdigit(ch=getc());res=res*10+num);
    18     (flag)&&(res=-res);
    19     #undef num
    20     return res;
    21 }
    22 const int N=30005,M=N*500;
    23 int ver[M],Next[M],head[M],edge[M],tot;
    24 int vis[M],dis[M];queue<int> q;
    25 int b[N],p[N],n,m,block,ans;
    26 inline void add(int u,int v,int e){
    27     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
    28 }
    29 int spfa(int s,int t){
    30     memset(dis,0x3f,sizeof(dis));
    31     memset(vis,0,sizeof(vis));
    32     q.push(s),vis[s]=1,dis[s]=0;
    33     while(!q.empty()){
    34         int u=q.front();q.pop(),vis[u]=0;
    35         for(int i=head[u];i;i=Next[i]){
    36             int v=ver[i];
    37             if(cmin(dis[v],dis[u]+edge[i]))
    38             if(!vis[v]) q.push(v),vis[v]=1;
    39         }
    40     }
    41     return dis[t];
    42 }
    43 int main(){
    44 //    freopen("testdata.in","r",stdin);
    45     n=read(),m=read();
    46     block=min(100,(int)sqrt(n));
    47     for(int i=1;i<=block;++i){
    48         for(int j=0;j+i<n;++j){
    49             add(id(j,i),id(j+i,i),1),
    50             add(id(j+i,i),id(j,i),1);
    51         }
    52         for(int j=0;j<n;++j) add(id(j,i),j,0);
    53     }
    54     for(int i=0;i<m;++i){
    55         b[i]=read(),p[i]=read();
    56         if(p[i]<=block) add(b[i],id(b[i],p[i]),0);
    57         else{
    58             for(int j=b[i]-p[i];j>=0;j-=p[i])
    59             add(b[i],j,(b[i]-j)/p[i]);
    60             for(int j=b[i]+p[i];j<n;j+=p[i])
    61             add(b[i],j,(j-b[i])/p[i]);
    62         }
    63     }
    64     ans=spfa(b[0],b[1]);
    65     printf("%d
    ",ans!=0x3f3f3f3f?ans:-1);
    66     return 0;
    67 }
  • 相关阅读:
    ArcGIS Server 9.3 JavaScript API实战一个具体的小系统示例介绍
    感冒太难受了
    ACM考试的题目,收藏,有空做做
    用Java在Dos下,用纯字符画图
    考ACM需要的知识(转)
    换个风格,换种心情
    (C#)ACM考试题的第一题
    .net连Access的OleDb数据库连接字符串写法
    (C#)ACM考试题的第二题
    辗转相除
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9683152.html
Copyright © 2020-2023  润新知