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 }

 

posted @ 2020-02-17 21:56  小又又  阅读(124)  评论(0编辑  收藏  举报