BZOJ 4070: [Apio2015]雅加达的摩天楼 根号分治+spfa

此题卡Dijkstra...

Code: 

#include <bits/stdc++.h>  
#define N 30005   
#define M 4000000
#define ll long long  
#define inf 100000000
#define E 14300000
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;      
ll d[M];   
int n,m,block,cnt,edges,s,t;          
int id[N][103],hd[M],to[E],nex[E],val[E],done[M];       
struct Node 
{
    int u; 
    ll dis; 
    Node(int u=0,ll dis=0):u(u),dis(dis){}    
    bool operator<(Node b) const
    {
        return b.dis<dis;         
    }
};   
priority_queue<Node>q;   
void add(int u,int v,int c) 
{
    // ++edges;         
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;   
} 
void Dijkstra() 
{  
    memset(d,0x3f,sizeof(d)); 
    for(d[s]=0,q.push(Node(s,0));!q.empty();) 
    {
        Node e=q.top(); q.pop(); 
        int u=e.u;  
        if(done[u]) continue;  
        done[u]=1; 
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i]; 
            if(d[v]>d[u]+val[i]) 
            {
                d[v]=d[u]+val[i]; 
                q.push(Node(v, d[v]));   
            }
        }
    }   
}
int main() 
{  
    int i,j,k;  
    // setIO("input"); 
    scanf("%d%d",&n,&m); 
    block=min(100,(int)sqrt(n));        
    cnt = n + 23;     
    for(i=1;i<=block;++i)        
    {
        for(j=0;j<i;++j)               
        {
            for(k=j;k<n;k+=i)          
            {
                id[k][i]=++cnt;   
                add(cnt,k,0);      
                if(k>=i)    
                    add(cnt-1,cnt,1), add(cnt,cnt-1,1);    
            }
        }
    }
    for(i=1;i<=m;++i)  
    {
        int a,b; 
        scanf("%d%d",&a,&b);    
        if(i==1) s=a;        
        if(i==2) t=a;   
        if(b<=block) 
            add(a, id[a][b], 0);    
        else 
        {
            int tt=0; 
            for(j=a-b;j>=0;j-=b) add(a,j,++tt);        
            tt=0; 
            for(j=a+b;j<n;j+=b) add(a,j,++tt);     
        }
    }  
    // printf("%d %d\n",cnt,edges);            
    Dijkstra(); 
    printf("%lld\n",d[t]>=inf?-1:d[t]);   
    return 0;  
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值