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

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. POJ2387(dijkstra堆优化)

    Til the Cows Come Home Bessie is out in the field and wants to get back to the barn to get as much s ...

  4. POJ 2502 Subway / NBUT 1440 Subway / SCU 2186 Subway(图论,最短距离)

    POJ 2502 Subway / NBUT 1440 Subway / SCU 2186 Subway(图论,最短距离) Description You have just moved from a ...

  5. hdu 2544 单源最短路问题 dijkstra+堆优化模板

    最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

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

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

  7. Dijkstra堆优化学习

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

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

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

  9. hdu3790 dijkstra+堆优化

    题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=3790 分析:dijkstra没有优化的话,复杂度是n*n,优化后的复杂度是m*logm,n是顶点数,m ...

随机推荐

  1. (C语言)数组与指针的区别

    以前常常听过这种说法,说数组和指针这两者比较像,但是不能混淆,可是一直没能理解.刚刚在李云的<专业嵌入式软件开发>中,看了讲述数组与指针区别的一章,似乎有所领悟.本着知乎上看到的这张图,我 ...

  2. LINQ查询操作符之First、FirstOrDefault、Last、LastOrDefault、ElementAt、ElementAtOrDefault、Contains、Any、All、Coun

    ·First - 返回集合中的第一个元素:不延迟 ·FirstOrDefault - 返回集合中的第一个元素(如果没有则返回默认值):不延迟 ·Last - 返回集合中的最后一个元素:不延迟 ·Las ...

  3. linux mint konsole终端模拟器 字符之间空格

    最近安装了linux mint 发现里面的终端是:konsole终端模拟器 ,问题是每次输字符随着输入字符越来越多,字符与光标之间的距离也越来越大(看上去像是自动添加了空格一样), 同时在使用vi时, ...

  4. Oracle 数据集成的实际解决方案

    就针对市场与企业的发展的需求,Oracle公司提供了一个相对统一的关于企业级的实时数据解决方案,即Oracle数据集成的解决方案.以下的文章主要是对其解决方案的具体描述,望你会有所收获. Oracle ...

  5. POJ 2387 Til the Cows Come Home (最短路 dijkstra)

    Til the Cows Come Home 题目链接: http://acm.hust.edu.cn/vjudge/contest/66569#problem/A Description Bessi ...

  6. 【转】Android 菜单(OptionMenu)大全 建立你自己的菜单--不错

    原文网址:http://www.cnblogs.com/salam/archive/2011/04/04/2005329.html 菜单是用户界面中最常见的元素之一,使用非常频繁,在Android中, ...

  7. SPOJ 0287 Smart Network Administrator

    题目大意:一座村庄有N户人家.只有第一家可以连上互联网,其他人家要想上网必须拉一根缆线通过若干条街道连到第一家.每一根完整的缆线只能有一种颜色.网管有一个要求,各条街道内不同人家的缆线必须不同色,且总 ...

  8. (转)JAVA路径问题及命令行编译运行基础(linux下)

    原地址: http://blog.csdn.net/biaobiaoqi/article/details/6846274 java的运行机制的基本概念: 源文件 也就是我们熟知的.java文件. 类文 ...

  9. Moon.Orm 5.0 (MQL版)

    Moon.Orm 5.0 (MQL版) 实战实例Moon.Orm 5.0 革命性的设计 打造最便捷的异步分页技术(提供下载) 摘要: 一.建一个项目(以WebForm为例)配置文件配置(注意您自己的路 ...

  10. 怎么在ng-repeat生成的元素上操作dom

    这个问题其实对初学者来说,都 有这样的经历,用ng-repeat生成的元素用js怎么也获取不到;这个其中原由是:angular拥有自动化渲染DOM的特性,它能帮助我们专注于操作数据,而页面的渲染则由a ...