BZOJ 2834: 回家的路 Dijkstra

按照横,竖为方向跑一个最短路即可,算是水题~ 

#include <bits/stdc++.h>    
#define N 200005    
#define E 2000000 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;      
int n,m,tot,edges,s,T;     
int hd[E],to[E],nex[E],val[E],d[E],done[E],id[E][2];            
void addedge(int u,int v,int c) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;     
}
struct Point
{
    int x,y,id;   
    Point(int x=0,int y=0):x(x),y(y){}   
}t[N];     
struct Node
{
    int u,dis; 
    Node(int u=0,int dis=0): u(u),dis(dis){} 
    bool operator<(Node b) const 
    {
        return b.dis<dis;    
    }
}; 
priority_queue<Node>q;     
bool cmpx(Point a,Point b) 
{
    return a.x==b.x?a.y<b.y:a.x<b.x;    
}  
bool cmpy(Point a,Point b) 
{
    return a.y==b.y?a.x<b.x:a.y<b.y;    
}
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);         
    for(i=2;i<=m+1;++i) 
    { 
        scanf("%d%d",&t[i].x,&t[i].y);    
        id[i][0]=++tot;   
        id[i][1]=++tot;                   
        t[i].id=i;     
    }    
    scanf("%d%d",&t[1].x,&t[1].y); 
    id[1][0]=++tot; 
    id[1][1]=++tot;  
    t[1].id=1;
    m+=2;            
    scanf("%d%d",&t[m].x,&t[m].y); 
    id[m][0]=++tot; 
    id[m][1]=++tot;  
    t[m].id=m;            
    for(i=1;i<=m;++i) 
    {
        addedge(id[i][0],id[i][1],1); 
        addedge(id[i][1],id[i][0],1);   
    }
    sort(t+1,t+1+m,cmpx);  
    for(i=1;i<=m;i=j) 
    {
        for(j=i;j<=m&&t[j].x==t[i].x;++j);    
        for(k=i+1;k<j;++k) 
        { 
            addedge(id[t[k-1].id][1], id[t[k].id][1], 2 * (t[k].y-t[k-1].y));     
            addedge(id[t[k].id][1], id[t[k-1].id][1], 2 * (t[k].y-t[k-1].y));     
        }
    }  
    sort(t+1,t+1+m,cmpy);    
    for(i=1;i<=m;i=j) 
    {
        for(j=i;j<=m&&t[j].y==t[i].y;++j);    
        for(k=i+1;k<j;++k) 
        { 
            addedge(id[t[k-1].id][0], id[t[k].id][0], 2 * (t[k].x-t[k-1].x));     
            addedge(id[t[k].id][0], id[t[k-1].id][0], 2 * (t[k].x-t[k-1].x));          
        }
    }  

    s=0, T=++tot;    

    addedge(s, id[1][0], 0);   
    addedge(s, id[1][1], 0);   

    addedge(id[m][0], T, 0);  
    addedge(id[m][1], T, 0);      
    Dijkstra();      
    printf("%d\n",d[T]);         
    return 0;   
}

  

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值