做这道题的动机就是想练习一下堆的应用,顺便补一下好久没看的图论算法。

Dijkstra算法概述

//从0出发的单源最短路

dis[][] = {INF}
ReadMap(dis);
for i = 0 -> n - 1
    d[i] = dis[0][i]
while u = GetNearest(1 .. n - 1, !been[])
    been[u] = 1
    for_each edge from u
        d[edge.v] = min(d[edge.v], d[u] + dis[u][edge.v])

上述算法遍历所有节点,每次 GetNearest() 循环一次,并遍历了所有边,算法复杂度 O(V2+E) = O(V2)

其中 GetNearest() 总取未去过的点中 d[] 最小的点,可以用小根堆维护 d[] 数组优化。

堆优化算法概述

//从0出发的单源最短路

dis[][] = {INF}
ReadMap(dis);
for i = 0 -> n - 1
    d[i] = dis[0][i]
heap = BuildHeap(d[], n - 1)
while u = heap.pop()
    been[u] = 1
    for_each edge from u
        if IsBetterDist()
            d[edge.v] = d[u] + dis[u][edge.v]
            heap.up(heap.IndexOf(edge.v))

建堆 O(VlogV),n次pop() O(VlogV),遍历边并更新堆 O(ElogV),优化算法复杂度 O(2VlogV+ElogV) = O((V+E)logV)

其他心得

* 几何类最短路一定要判重点

//POJ 2502
//Dijkstra 堆优化试水
//飘忽不定的迷离的数据
//AC 2016-10-17

#define HEAP_OPTIMIZE

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define MAXN (200 + 2) + 10
#define SUB_SPEED (40000.0 / 60.0)
#define WALK_SPEED (10000.0 / 60.0)
#define INF 0x7f7f7f7f
using namespace std;

inline double sqr(int x){
    return x * x;
}

struct point {
    int x, y;
    point(){}
    point(int X, int Y): x(X), y(Y){}
    inline double norm(){
        return sqrt(sqr(x) + sqr(y));
    }
    friend point operator - (const point &p1, const point &p2){
        return point(p1.x - p2.x, p1.y - p2.y);
    }
    friend bool operator == (const point &p1, const point &p2){
        return (p1.x == p2.x) && (p1.y == p2.y);
    }
}pt[MAXN];

int n = 0;

int IndexOf(const point &p){
    for (int i = 0; i < n; i++){
        if (pt[i] == p)
            return i;
    }
    return n;
}

double dis[MAXN][MAXN], d[MAXN];
bool been[MAXN];

struct BHeap{
    int heap[MAXN], n, index[MAXN];
    BHeap(): n(0){}
    BHeap(int N): n(0){
        for (int i = 1; i <= N; i++)
            push(i);
    }
    void down(int i){
        for (int j = 2 * i; j <= n; j <<= 1){
            j += j < n && d[heap[j]] > d[heap[j + 1]];
            if (d[heap[j]] < d[heap[i]]){
                swap(index[heap[i]], index[heap[j]]);
                swap(heap[i], heap[j]);
                i = j;
            }
            else break;
        }
    }
    void up(int i){
        for (int j = i/2; j > 0; j >>= 1){
            if (d[heap[j]] > d[heap[i]]){
                swap(index[heap[i]], index[heap[j]]);
                swap(heap[i], heap[j]);
                i = j;
            }
            else break;
        }
    }
    void push(int a){
        heap[++n] = a;
        index[a] = n;
        up(n);
    }
    int pop(){
        if (!n) return 0;
        swap(index[heap[1]], index[heap[n]]);
        swap(heap[1], heap[n--]);
        down(1);
        return heap[n + 1];
    }
}heap;

int main(){
    freopen("fin.c", "r", stdin);
    for (int i = 0; i < MAXN; i++)
        for(int j = 0; j < MAXN; j++)
			if (i == j) dis[i][j]=0;
			else dis[i][j] = INF;
    scanf("%d%d%d%d", &pt[0].x, &pt[0].y, &(pt[1].x), &pt[1].y);
    n = 2;
    dis[0][1] = dis[1][0] = (pt[0] - pt[1]).norm() / WALK_SPEED;
    point p;
    while (~scanf("%d%d", &p.x, &p.y)){
        int iter = IndexOf(p), olditer = - 1;
        if (iter == n){
            pt[n++] = p;
            for (int i = 0; i < n; i++){
                dis[i][n - 1] = dis[n - 1][i] = (pt[n - 1] - pt[i]).norm() / WALK_SPEED;
            }
        }
        olditer = iter;
        while (scanf("%d%d", &p.x, &p.y), ~p.x && ~p.y){
            int iter = IndexOf(p);
            if (iter == n){
                pt[n++] = p;
                for (int i = 0; i < n; i++){
                    if (i != olditer)
                        dis[i][n - 1] = dis[n - 1][i] = (pt[n - 1] - pt[i]).norm() / WALK_SPEED;
                    else
                        dis[i][n - 1] = dis[n - 1][i] = (pt[n - 1] - pt[i]).norm() / SUB_SPEED;
                }
            }
            else dis[olditer][iter] = dis[iter][olditer] = (pt[iter] - pt[olditer]).norm() / SUB_SPEED;
            olditer = iter;
        }
    }
    for (int i = 1; i < n; i++)
        d[i] = dis[0][i];
    #ifdef HEAP_OPTIMIZE
        heap = BHeap(n - 1);
    #endif
    while (
    #ifdef HEAP_OPTIMIZE
        int v = heap.pop()
    #else
        1
    #endif
    ){
        #ifndef HEAP_OPTIMIZE
	        double minn = INF;
	        int v = - 1;
	        for (int i = 1; i < n; i ++)
	            if ((!been[i])&&(d[i] < minn)){
	                minn = d[i];
	                v = i;
	            }
	        if (!~v) break;
        #endif
        been[v] = 1;
        for (int i = 1; i < n; i++){
            if (!been[i]){
                if (d[v] + dis[v][i] < d[i]){
                    d[i] = d[v] + dis[v][i];
                    #ifdef HEAP_OPTIMIZE
                        heap.up(heap.index[i]);
                    #endif
                }
            }
        }
    }
    printf("%.f\n", d[1]);
}

POJ 2502 - Subway Dijkstra堆优化试水的更多相关文章

  1. POJ 2502 Subway (Dijkstra 最短+建设规划)

    Subway Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6689   Accepted: 2176 Descriptio ...

  2. Bzoj 2834: 回家的路 dijkstra,堆优化,分层图,最短路

    2834: 回家的路 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 62  Solved: 38[Submit][Status][Discuss] D ...

  3. POJ 1511 - Invitation Cards 邻接表 Dijkstra堆优化

    昨天的题太水了,堆优化跑的不爽,今天换了一个题,1000000个点,1000000条边= = 试一试邻接表 写的过程中遇到了一些问题,由于习惯于把数据结构封装在 struct 里,结果 int [10 ...

  4. Dijkstra堆优化学习

    最短路径例题 今天特地学习了Dijkstra的堆优化(主要是慕名已久). 我们需要一个堆来记录[编号,到编号这个点的最短路径值(当然只是当前的)] 与原来的Dijkstra操作基本一致,主要有以下几点 ...

  5. 【Dijkstra堆优化】洛谷P2243电路维修

    题目背景 Elf 是来自Gliese 星球的少女,由于偶然的原因漂流到了地球上.在她无依无靠的时候,善良的运输队员Mark 和James 收留了她.Elf 很感谢Mark和James,可是一直也没能给 ...

  6. (简单) POJ 2502 Subway,Dijkstra。

    Description You have just moved from a quiet Waterloo neighbourhood to a big, noisy city. Instead of ...

  7. Dijkstra+计算几何 POJ 2502 Subway

    题目传送门 题意:列车上行驶40, 其余走路速度10.问从家到学校的最短时间 分析:关键是建图:相邻站点的速度是40,否则都可以走路10的速度.读入数据也很变态. #include <cstdi ...

  8. POJ 2502 Subway(迪杰斯特拉)

    Subway Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6692   Accepted: 2177 Descriptio ...

  9. POJ 2502 Subway

    Subway Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4928   Accepted: 1602 Descriptio ...

随机推荐

  1. jQuery选择器总结

    jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法   $("#myELement")    选择id值等于myElement的元素,id值不能重复在文档中 ...

  2. MySQL NoInstall 配置

    1.下载 mysql-mysql-5.1.55-win32.zip 2. 解压缩到任何一个目录,最好目录名称不要有空格: 例如:C:\mysql 3. 删除Embedded,include,lib,m ...

  3. Linux初学:(二)Shell环境与命令基础

    博客园(FOREVER_ENJOY):http://www.cnblogs.com/zyx1314/ 本文版权归作者所有:欢迎转载!请注明文章作者和原文连接 Shell是什么? 1. Shell作为应 ...

  4. MBP使用笔记

    1. 链接测试机命令: 登录:ssh ria@000.000.000.000 然后输入密码即可 退出:exit 2. SwitchySharp导入的是bak文件. 3. 使用goagentFQ的使用的 ...

  5. September 22nd 2016 Week 39th Thursday

    Things won are done, the soul of joy lies in the doing. 得到即是完结,快乐的精髓在于过程. Things won are done, thing ...

  6. Xcode 设置 ARC&amp;MRC混用

    如果你的项目使用的非 ARC 模式,则为 ARC 模式的代码文件加入 -fobjc-arc 标签.如果你的项目使用的是 ARC 模式,则为非 ARC 模式的代码文件加入 -fno-objc-arc 标 ...

  7. bin/bash 和 /bin/sh 的区别

    今天在用ssh Secure shell 连接虚拟机中的Ubuntu编写程序时,想比对一下两个源代码有什么差别,但是在一个ssh 客户端下不断的切换很是费劲.于是想着在主机中再添加一个用户.我原本用s ...

  8. membership db注册工具

    C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe

  9. Win下循环进入目录启动执行某任务

    cd tldlq for /D %%s in (*) do ( cd %%s start "" LoginGate.exe start "" GameGate. ...

  10. Ajax动态滚动加载数据

    看新浪微博,人人网都有这样的效果:滚动条滚动到最下面的时候,新的数据就被自动加载出来了,今天亲自尝试了一下这个效果的实现. 最开始在CSDN上写了一版,功能比较简单,今天又增加了一个小功能:翻页到指定 ...