bzoj4152[AMPPZ2014] The Captain

题意

给出平面上n个点坐标,点(x1,y1)和点(x2,y2)之间有权值为\(min(abs(x1-x2),abs(y1-y2))\)的边,求1到n的最短路.

分析

老早就知道有这么个题但是一直不会
也许这就是蒟蒻吧.jpg
首先我们可以在(x1,y1)和(x2,y2)之间连两条边,权值分别为abs(x1-x2),abs(y1-y2),然后跑最短路,答案显然不变.
然后我们发现,对从左向右三个点A(x1,y1),B(x2,y2),C(x3,y3),满足x1<=x2<=x3,我们在AB之间连了权值为abs(x1-x2)的边,BC之间连了权值为abs(x2-x3)的边,就不需要在AC之间连权值为abs(x1-x3)的边了.
于是只需按横坐标排序后相邻的点之间连n-1条双向边,按纵坐标排序后相邻的点之间连n-1条双向边.这个边数就可以跑dijkstra了.
这个题还有个最小生成树版本:AtCoder Regular Contest 076D Built?

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=200005,maxm=1000005;
struct edge{
  int to,next,w;
}lst[maxm];int len=1,first[maxn];
void addedge(int a,int b,int w){
  lst[len].to=b;lst[len].w=w;lst[len].next=first[a];first[a]=len++;
}
struct node{
  int v,d;
  node(){}
  node(int _v,int _d){v=_v;d=_d;}
  bool operator <(const node &B)const{
    return d>B.d;
  }
};
bool vis[maxn];int dis[maxn];
int n;
void dijkstra(){
  for(int i=1;i<=n;++i)dis[i]=0x7f7f7f7f;
  dis[1]=0;
  priority_queue<node> q;
  q.push(node(1,0));
  while(!q.empty()){
    node tmp=q.top();q.pop();
    if(vis[tmp.v])continue;
    vis[tmp.v]=true;
    for(int pt=first[tmp.v];pt;pt=lst[pt].next){
      if(!vis[lst[pt].to]&&dis[lst[pt].to]>tmp.d+lst[pt].w){
	dis[lst[pt].to]=tmp.d+lst[pt].w;
	q.push(node(lst[pt].to,tmp.d+lst[pt].w));
      }
    }
  }
}
int x[maxn],y[maxn];
int seq[maxn];
bool cmpx(const int &a,const int &b){
  return x[a]<x[b];
}
bool cmpy(const int &a,const int &b){
  return y[a]<y[b];
}
int main(){
  scanf("%d",&n);
  for(int i=1;i<=n;++i)scanf("%d%d",x+i,y+i);
  for(int i=1;i<=n;++i)seq[i]=i;
  sort(seq+1,seq+n+1,cmpx);
  for(int i=1;i<n;++i){
    addedge(seq[i],seq[i+1],x[seq[i+1]]-x[seq[i]]);
    addedge(seq[i+1],seq[i],x[seq[i+1]]-x[seq[i]]);
  }
  sort(seq+1,seq+n+1,cmpy);
  for(int i=1;i<n;++i){
    addedge(seq[i],seq[i+1],y[seq[i+1]]-y[seq[i]]);
    addedge(seq[i+1],seq[i],y[seq[i+1]]-y[seq[i]]);
  }
  dijkstra();
  printf("%d\n",dis[n]);
  return 0;
}

posted @ 2017-07-01 19:53  liu_runda  阅读(131)  评论(0编辑  收藏  举报
偶然想到可以用这样的字体藏一点想说的话,可是并没有什么想说的. 现在有了:文化课好难