4152: [AMPPZ2014]The Captain
Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 1180 Solved: 452
[Submit][Status][Discuss]
Description
给定平面上的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
一道求最短路的题,每个点只用跟离它最近的四个点连边,所以先sort一遍,把x,y值从小到大排一遍,相邻的连起来。
最多就200000*4条边。
SPFA会被卡,(我就是一个不信邪然后刚了一上午无果的傻逼)
感觉SPFA无论如何优化都会被卡(可能是我自己太弱了),应该用dijkstra+堆优化
就当贴个板。这个算法也比较稳定,用来求最短路的话。
以后可以抛弃SPFA了
为什么很多人都觉得自己打的是SPFA+优先队列优化呢这明明是dijkstra+堆啊
//这道题是有多看不起SPFA
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ms(x,y) memset(x,y,sizeof(x))
#include<queue>
#define ll long long
#define xxx pair<long long,int>
using namespace std;
const int N = 200000 + 10;
const int M = N*4;
inline ll read()
{
ll data=0,w=1; char ch=0;
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
return data*w;
}
int n;
priority_queue<xxx,vector<xxx>,greater<xxx> >q;
struct Node{
ll x,y;
int i;
}a[N];
struct node{
int pre,v;
ll w;
}edge[M];
int num=0;
int head[N];
void addedge(int from,int to,ll w){
num++;
edge[num].pre=head[from];
edge[num].v=to;
edge[num].w=w;
head[from]=num;
}
bool cmp1(const Node &a,const Node &b){
return a.x<b.x;
}
bool cmp2(const Node &a,const Node &b){
return a.y<b.y;
}
void getmap(){
sort(a+1,a+n+1,cmp1);
for(register int i=2;i<=n;i++){
ll w=a[i].x-a[i-1].x;
addedge(a[i-1].i,a[i].i,w);
addedge(a[i].i,a[i-1].i,w);
}
sort(a+1,a+n+1,cmp2);
for(register int i=2;i<=n;i++){
ll w=a[i].y-a[i-1].y;
addedge(a[i-1].i,a[i].i,w);
addedge(a[i].i,a[i-1].i,w);
}
}
ll dis[N];
bool exist[N];
void dijkstra(){
ms(dis,127);ms(exist,0);
q.push(make_pair(0,1)),dis[1]=0;
while(!q.empty()){
int u=q.top().second;q.pop();
if(exist[u]) continue;
exist[u]=1;
for(int i=head[u];i;i=edge[i].pre){
int v=edge[i].v;
if(dis[v]>dis[u]+edge[i].w){
dis[v]=dis[u]+edge[i].w;
q.push(make_pair(dis[v],v));
}
}
}
}
int main(){
scanf("%d",&n);
for(register int i=1;i<=n;i++){
a[i].x=read(),a[i].y=read();
a[i].i=i;
}
getmap();
/* for(int i=head[1];i;i=edge[i].pre){
int v=edge[i].v;
printf("%d %d\n",v,edge[i].w);
}*/
dijkstra();
printf("%lld",dis[n]);
return 0;
}