• 图论---The Captain


    B-The Captain

    给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。

    Input

    第一行包含一个正整数n(2<=n<=200000),表示点数。
    接下来n行,每行包含两个整数x[i],yi,依次表示每个点的坐标。

    Output

    一个整数,即最小费用。

    Sample Input

    5
    2 2
    1 1
    4 5
    7 1
    6 7
    

    Sample Output

    2
    
    #include<cstdio>  
    #include<cstring>    
    #include<algorithm>  
    #include<queue> 
    #define N 200010
    #define inf 0x3f3f3f3f
    #define pa pair<long long, int>
    using namespace std;
    int head[N];
    long long dis[N];
    int n, num;
    bool vis[N];
    struct node
    {  
        int x, y, z;
    }a[N];
    priority_queue<pa, vector<pa>, greater<pa> > q;
    bool cmp_x(node x,node y)
    {
    	return x.x < y.x;
    }
    bool cmp_y(node x,node y)
    {
    	return x.y < y.y;
    }
    struct edge
    {
        int u, v, next;
        long long w;
        edge(){next=-1;}
    }ed[4*N];
    void build(int u,int v,int w)
    {  
        num++;
        ed[num].w=w;
        ed[num].v=v;
        ed[num].next=head[u];
        head[u]=num;
    }
    void SPFA()
    {
        memset(vis, 0, sizeof(vis));
        for(int i=1; i<=n; i++) dis[i]=inf;
        dis[1]=0;
        q.push(make_pair(0, 1));
        while(!q.empty())
        {
            int u=q.top().second;
            q.pop();
            if(vis[u])continue;
            vis[u]=1;
            for(int i=head[u]; i!=-1; i=ed[i].next)
            {
                int v=ed[i].v;
                if(dis[v]>dis[u]+ed[i].w)
                {
                    dis[v]=dis[u]+ed[i].w;
                    q.push(make_pair(dis[v], v));
                }
            }
        }
    }
    int main()  
    {  
        memset(head, -1, sizeof(head));
        scanf("%d", &n);  
        for (int i=1; i<=n; i++)  
        {  
            scanf("%d%d", &a[i].x, &a[i].y);  
            a[i].z=i;  
        }  
        sort(a+1, a+n+1, cmp_x);  
        for(int i=1; i<n; i++)
        {
            build(a[i].z, a[i+1].z, a[i+1].x-a[i].x),
            build(a[i+1].z, a[i].z, a[i+1].x-a[i].x);   
        } 
        sort(a+1, a+n+1, cmp_y);  
        for(int i=1; i<n; i++) 
        {
            build(a[i].z, a[i+1].z, a[i+1].y-a[i].y),
            build(a[i+1].z, a[i].z, a[i+1].y-a[i].y);   
        }
        SPFA();  
        printf("%lld
    ", dis[n]);  
        return 0;  
    }
    
    • 我们不难发现,如果有一个点P在M,N两个点之间,从M到N得代价一定大于从P到M再从P到N得代价。
    • 换言之,我们的边应该建在横纵坐标相邻的点之间。
    • 为此目的,我们把点们按照横坐标从小到大排序,再把点们按照纵坐标从小到大排序。然后直接按排好的顺序两辆排序。
    • 要用Dijkstra的话。。。除非你开堆优化的Dijkstra,否则是过不了的。
  • 相关阅读:
    BootStrap 智能表单系列 五 表单依赖插件处理
    BootStrap 智能表单系列 四 表单布局介绍
    BootStrap 智能表单系列 三 分块表单配置的介绍
    LinQ.OrderBy 多个字段排序
    ABP.NET CORE 遇到的小问题
    vs2017断点无效 当前不会命中断点 已设置断点单还未绑定
    DateTime 取年月日;字符串截取
    C# DateTime 多个时间段循环相加;两个时间段求差值
    ABP.Net Core 小白使用教程 附件:ABP.NET中文文档
    ASP.NET MVC+Easyui 后台管理系统的图片上传
  • 原文地址:https://www.cnblogs.com/orange-233/p/12320950.html
Copyright © 2020-2023  润新知