bzoj 4152 最短路SPFA

来源:互联网 发布:php上传文件到服务器 编辑:程序博客网 时间:2024/06/07 17:45

题目描述

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

思路

首先观察 一下题中距离的定义。
这里写图片描述
我们轻易地发现A到C的距离显然是A->B->C而非A->C。
贪心一下,最近的边只能是相邻的边(也就是说连边的过程中不能跨过别的点)。
所以说我们把所有的点先按x坐标排序,依次连接起来,y坐标同理。
直接用SPFA的话会被卡掉,这个时候可以用Dijkstra,当然我用的是堆优化SPFA也过了。

代码

#include<cstdio>  #include<cstring>    #include<algorithm>  #include<queue> using namespace std; #define N 200010   #define inf 0x3f3f3f3f #define pa pair<long long,int>  using namespace std;  struct Node {      int x,y,id;  }a[N];  int head[N];  long long dis[N];int n,num;  bool vis[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;    long long w;    int next;    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].id=i;      }      sort(a+1,a+n+1,cmp_x);      for(int i=1;i<n;i++)    {        build(a[i].id,a[i+1].id,a[i+1].x-a[i].x),        build(a[i+1].id,a[i].id,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].id,a[i+1].id,a[i+1].y-a[i].y),        build(a[i+1].id,a[i].id,a[i+1].y-a[i].y);       }    SPFA();      printf("%lld\n",dis[n]);      return 0;  }

我偷的他的图

原创粉丝点击