• Dijkstra--The Captain


    *传送

    给定平面上的n个点,定义$(x_1,y_1)$到$(x_2,y_2)$的费用为min(|$x_1$-$x_2$|,|$y_1$-$y_2$|),求从1号点走到n号点的最小费用。

    先给一段证明:给定三个x值,$x_1<x_2<x_3$。可得$x_2-x_1<x_3-x_2<x_3-x_1$,对于最小费用,很明显只有$x_2-x_1$是有用的。对y同理,同时要注意我们不能把$x$和$y$两者混谈。由此我们得到了一个思路,分层图x和y跑一次最短路。

    首先两个$cmp$函数对$n$个点进行的两次排序(注意在之前把点的序号也存下来):

    1 bool cmp1(node a,node b)
    2 {
    3     return a.x<b.x;
    4 }
    5 bool cmp2(node a,node b)
    6 {
    7     return a.y<b.y;
    8 }

    链式前向星构图:

     1 struct edge
     2 {
     3     int next,to,w;
     4 }edge[maxn];
     5 void add(int u,int v,int w)
     6 {
     7     edge[++tot].w=w;
     8     edge[tot].to=v;
     9     edge[tot].next=head[u];
    10     head[u]=tot;
    11 }
    12     sort(a+1,a+n+1,cmp1);
    13     for (int i = 1;i < n;i++)
    14     {
    15         add(a[i].id,a[i+1].id,abs(a[i].x-a[i+1].x));
    16         add(a[i+1].id,a[i].id,abs(a[i].x-a[i+1].x));
    17     }
    18     sort(a+1,a+n+1,cmp2);
    19     for (int i = 1;i < n;i++)
    20     {
    21         add(a[i].id,a[i+1].id,abs(a[i].y-a[i+1].y));
    22         add(a[i+1].id,a[i].id,abs(a[i].y-a[i+1].y));
    23     }

    然后是很标准的dij板子:

     1 void Dijkstra(int S)
     2 {
     3     q.push(make_pair(0,S)); memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); dis[S] = 0;
     4     while(!q.empty())
     5     {
     6         int x = q.top().second; 
     7         q.pop(); 
     8         if(vis[x])
     9             continue; 
    10         vis[x] = 1;
    11         for(int i=head[x];i!=0;i=edge[i].next)
    12         {
    13             int to1=edge[i].to;
    14             if(dis[to1] > dis[x] + edge[i].w)
    15             {
    16                 dis[to1] = dis[x] + edge[i].w ;
    17                 q.push(make_pair(-dis[to1],to1));
    18             }
    19         }
    20     }
    21     return;
    22 }

    完整代码如下:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <queue>
     6 #include <cmath>
     7 using namespace std;
     8 #define ll long long
     9 int n;
    10 const int maxn=1000000;
    11 priority_queue< pair<int ,int > >q;
    12 int dis[maxn],vis[maxn];
    13 int tot=0,head[maxn];
    14 int read(){
    15     int x=1,a=0;
    16     char ch=getchar();
    17     while (ch < '0'||ch > '9'){
    18         if (ch == '-') x=-1;
    19         ch = getchar();
    20     }
    21     while (ch <= '9'&&ch >= '0')
    22     {
    23         a = a*10 + ch- '0';
    24         ch=getchar();
    25     }
    26     return x*a;
    27 }
    28 struct node
    29 {
    30     int x,y,id;
    31 }a[maxn];
    32 struct edge
    33 {
    34     int next,to,w;
    35 }edge[maxn];
    36 void add(int u,int v,int w)
    37 {
    38     edge[++tot].w=w;
    39     edge[tot].to=v;
    40     edge[tot].next=head[u];
    41     head[u]=tot;
    42 }
    43 bool cmp1(node a,node b)
    44 {
    45     return a.x<b.x;
    46 }
    47 bool cmp2(node a,node b)
    48 {
    49     return a.y<b.y;
    50 }
    51 void Dijkstra(int S)
    52 {
    53     q.push(make_pair(0,S)); memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); dis[S] = 0;
    54     while(!q.empty())
    55     {
    56         int x = q.top().second; 
    57         q.pop(); 
    58         if(vis[x])
    59             continue; 
    60         vis[x] = 1;
    61         for(int i=head[x];i!=0;i=edge[i].next)
    62         {
    63             int to1=edge[i].to;
    64             if(dis[to1] > dis[x] + edge[i].w)
    65             {
    66                 dis[to1] = dis[x] + edge[i].w ;
    67                 q.push(make_pair(-dis[to1],to1));
    68             }
    69         }
    70     }
    71     return;
    72 }
    73 int main()
    74 {
    75     n=read();
    76     for (int i = 1;i <= n;i++)
    77     {
    78         a[i].x=read(),a[i].y=read();
    79         a[i].id=i;
    80     }
    81     sort(a+1,a+n+1,cmp1);
    82     for (int i = 1;i < n;i++)
    83     {
    84         add(a[i].id,a[i+1].id,abs(a[i].x-a[i+1].x));
    85         add(a[i+1].id,a[i].id,abs(a[i].x-a[i+1].x));
    86     }
    87     sort(a+1,a+n+1,cmp2);
    88     for (int i = 1;i < n;i++)
    89     {
    90         add(a[i].id,a[i+1].id,abs(a[i].y-a[i+1].y));
    91         add(a[i+1].id,a[i].id,abs(a[i].y-a[i+1].y));
    92     }
    93     Dijkstra(1);
    94     cout<<dis[n];
    95     return 0;
    96 }
  • 相关阅读:
    Bootstrap 2.2.2 的新特性
    Apache POI 3.9 发布,性能显著提升
    SQL Relay 0.48 发布,数据库中继器
    ProjectForge 4.2.0 发布,项目管理系统
    红帽企业 Linux 发布 6.4 Beta 版本
    红薯 快速的 MySQL 本地和远程密码破解
    MariaDB 宣布成立基金会
    Percona XtraBackup 2.0.4 发布
    Rocks 6.1 发布,光盘机群解决方案
    精通Servlet研究,HttpServlet的实现追究
  • 原文地址:https://www.cnblogs.com/very-beginning/p/12323915.html
Copyright © 2020-2023  润新知