zoukankan      html  css  js  c++  java
  • 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
    ",dis[n]);
      return 0;
    }
    
    
  • 相关阅读:
    [Android Pro] Android源码编译之Nexus5真机编译
    [设计模式] 策略模式(Strategy)
    [Android] Anreoid repo 切换分支
    [Android] repo 下载Android源码(国内镜像)
    [Android] osx下如何使用SublimeText阅读Android系统源码
    [Ubuntu] ubuntu的tty下挂载移动硬盘拷贝数据
    Elasticsearch
    Flink简介
    SQL中instr和like的使用区别
    count(1) 与 count(*) 比较
  • 原文地址:https://www.cnblogs.com/liu-runda/p/7103297.html
Copyright © 2011-2022 走看看