zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    ubuntu下查看环境变量
    ubuntu关闭自动更新、打开 ubuntu 的 apport 崩溃检测报告功能
    Ubuntu 配置AP总结
    ubuntu 12.04亮度无法调节和无法保存屏幕亮度解决办法(echo_brightness)
    Ubuntu 13.04 双显卡安装NVIDIA GT 630M驱动
    Linux下添加硬盘,分区,格式化详解
    Eclipse启动分析
    “蚁族” 的生活方式画像
    Ubuntu下的防火墙
    Ubuntu下的杀毒
  • 原文地址:https://www.cnblogs.com/very-beginning/p/12323915.html
Copyright © 2011-2022 走看看