hud2544dijkstra+堆优化

该算法对于稠密图更加有效:

对于给出具有非负权重的边和源顶点S的图G,算法可在O(mlogn)时间内找出从s点到其他每一个顶点的距离。

如果图是稠密的,即对于某个ε>0,m>=n^(1+ε),可以被改善在O(m/ε)内执行。(m为图的边数,n为图的定点数)

最小堆模板:

 1 struct HeapElement {
 2     // key存储顶点序号,value存储到该顶点的最短距离
 3     int key, value;
 4 };
 5 struct MinHeap {
 6     HeapElement heap[MAXN];
 7     int position[MAXN];
 8     int size; // 顶点数
 9     void init() {
10         heap[size=0].value = -INF;
11         memset(position, 0, sizeof(position));
12     }
13     void insert(int key, int value) {
14         heap[++size].key = key;
15         heap[size].value = value;
16         position[key] = size;
17         siftUp(size);
18     }
19     void decrease(int index) {
20         int x = heap[index].value;
21         int y = heap[size].value;
22         -- size;
23         if (index == size+1)
24             return;
25
26         swap(heap[index], heap[size+1]);
27         if (y >= x) {
28             siftDown(index);
29         } else {
30             siftUp(index);
31         }
32     }
33     int delmin() {
34         int x = heap[1].key;
35         decrease(1);
36         return x;
37     }
38     void siftUp(int index) {
39         while (index > 1) {
40             if (heap[index].value < heap[index/2].value) {
41                 swap(heap[index],heap[index/2]);
42             } else {
43                 break;
44             }
45             index /= 2;
46         }
47     }
48     void siftDown(int index) {
49         while (index*2 <= size) {
50             index *= 2;
51             if (index < size && heap[index].value > heap[index+1].value) {
52                 ++ index;
53             }
54             if (heap[index].value < heap[index/2].value) {
55                 swap(heap[index],heap[index/2]);
56             } else {
57                 break;
58             }
59         }
60     }
61     void makeHeap() {
62         for (int i = size/2; i > 0; -- i)
63             siftDown(i);
64     }
65     void swap(HeapElement &a, HeapElement &b) {
66         HeapElement temp = a;
67         a = b;
68         b = temp;
69         int tmp = position[a.key];
70         position[a.key] = position[b.key];
71         position[b.key] = tmp;
72     }
73 }H;

代码实现:(hdu2544)

#include <iostream>
#define INF 0x7FFFFFFF
using namespace std;

const int SIZE = 105;
int dist[SIZE];
int G[SIZE][SIZE];
bool vis[SIZE];
struct HeapElement {
    int key, value;
};
void swap(HeapElement &ha, HeapElement &hb) {
    int key = ha.key;
    int value = ha.value;
    ha.key = hb.key;
    ha.value = hb.value;
    hb.key = key;
    hb.value = value;
};
// 使用邻接表储存图,线性表储存堆
struct MinHeap {
    HeapElement heap[SIZE];
    int n;    // 顶点数    

    void makeheap() {
        for (int i = n/2; i > 0; -- i)
            siftDown(i);
    };
    void siftUp(int index) {
        int k = index;
        while (k > 1) {
            if (heap[k].value < heap[k/2].value) {
                swap(heap[k],heap[k/2]);
            } else {
                break;
            }
            k /= 2;
        }
    };
    void siftDown(int index) {
        int k = index;
        while (k*2 <= n) {
            k *= 2;
            if (k < n && heap[k].value > heap[k+1].value) {
                ++ k;
            }
            if (heap[k].value < heap[k/2].value) {
                swap(heap[k],heap[k/2]);
            } else {
                break;
            }
        }
    };
    void insert(HeapElement element) {
        heap[++n] = element;
        siftUp(n);
    };
    void decrease(int index) {
        int x = heap[index].value;
        int y = heap[n].value;
        n -= 1;

        // 若删除节点位于最末位置,则删除成功,无需其他操作。
        if (index == n+1)
            return;

        heap[index] = heap[n+1];
        if (y >= x) {
            siftDown(index);
        } else {
            siftUp(index);
        }
    };
    int decreaseMin() {
        int x = heap[1].key;
        decrease(1);
        return x;
    };
}H;

void dijkstra(int src, int n) {
    int i, j, w;
    bool flag;

    for (i = 1; i <= n; ++ i) {
        if (G[i][src] != INF) {
            dist[i] = G[src][i];
            HeapElement h = {i, dist[i]};
            H.insert(h);
        } else {
            dist[i] = INF;
        }
    }

    memset(vis, false, sizeof(vis));
    vis[src] = true;
    dist[src] = 0;

    for (i = 1; i < n; ++ i) {

        int node = H.decreaseMin();
        vis[node] = true;

        for (w = 1; w <= n; ++ w) {
            flag = false;
            if (!vis[w] && G[node][w] != INF) {
                if (dist[node] < dist[w] - G[node][w]) {
                    dist[w] = dist[node] + G[node][w];

                }
                for (j = 1; j <= H.n; ++ j) {
                        if (H.heap[j].key == w) {
                            H.heap[j].value = dist[w];
                            flag = true;
                            break;
                        }
                    }    

                if (!flag) {
                    HeapElement h = {w, dist[w]};
                    H.insert(h);
                } else {
                    H.siftUp(j);
                }
            }
        }
    }
};

void init(int n) {
    for (int i = 1; i <= n; ++ i)
        for (int j = 1; j <= n; ++ j)
            G[i][j] = INF;
    H.n = 0;
};

int main()
{
    int N, M, a, b, c;

    //freopen("C:\\Users\\Smile\\test.txt","r",stdin);
    //freopen("C:\\Users\\Smile\\out.txt", "w", stdout);

    while (scanf("%d%d",&N,&M)!=EOF, N&&M) {
        init(N);

        for (int i = 0; i < M; ++ i) {
            scanf("%d%d%d",&a,&b,&c);
            if (G[a][b] > c) {
                G[a][b] = c;
                G[b][a] = c;
            }
        }

        dijkstra(1, N);

        printf("%d\n",dist[N]);
    }
}

  

时间: 2024-10-10 04:34:06

hud2544dijkstra+堆优化的相关文章

dij+堆优化

写这个dij+堆优化的原因是有些地方卡SPFA,只能搞这个: 香甜的奶油: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<ctime> 7 #include<vector> 8 #include<algorithm> 9 #include&

[转]浅谈dijkstra堆优化

众所周知的,dijkstra是图论算法中求单源最短路的一种简单求法.可能有人会说SPFA比dijkstra要实用,而且可以用于求存在负边权的情况,但是dijkstra有着他的优点——其运行速度上优于SPFA. (PS.需要堆进行优化.) 我们先看一道经典(水)题: 平面上有n个点(n<=100),每个点的坐标均在-10000~10000之间.其中的一些点之间有连线. 若有连线,则表示可从一个点到达另一个点,即两点之间有通路,通路的距离为两点之间的直线距离.现在的任务是找出从入点到出点之间的最短路

Dij的堆优化

#include<algorithm> #include<iostream> #include<cstdio> #include<cstring> #include<queue> #define M 100000 #define pa pair<int,int>//优先比较第一个元素 using namespace std; int d[M],n,m,cnt,head[M],next[M],u[M],dis[M],num,s,t; b

hdu1245+dij,堆优化

有一片100*100的湖泊,中心坐标(0,0),即湖泊右上角的坐标是(50,50),湖泊中间有一片以(0,0)为圆心,15为直径的圆形陆地.现有一个人在陆地,湖泊中散布着一些点可以踩,这个人要利用这些点跳到岸上,求最短路径和最短路径下的最短步数. spfa莫名其妙的超时,dij+堆优化反而能过...可能spfa更适合有向图吧. 使用vector<vector<node> > g这种双重结构时,最好先g.resize(N)设置一下容量,否则直接插入会出错. 1 #include<

bzoj3040 最短路+配对堆优化

3040: 最短路(road) Time Limit: 60 Sec  Memory Limit: 200 MBSubmit: 1859  Solved: 564[Submit][Status][Discuss] Description N个点,M条边的有向图,求点1到点N的最短路(保证存在).1<=N<=1000000,1<=M<=10000000 Input 第一行两个整数N.M,表示点数和边数.第二行六个整数T.rxa.rxc.rya.ryc.rp. 前T条边采用如下方式生成

SPOJ 15. The Shortest Path 堆优化Dijsktra

You are given a list of cities. Each direct connection between two cities has its transportation cost (an integer bigger than 0). The goal is to find the paths of minimum cost between pairs of cities. Assume that the cost of each path (which is the s

BZOJ 3040 最短路(road) 堆优化Dijkstra

题目大意:最短路. 思路:最短路. 贴一份比较高效的堆优化Dij模板吧. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define _MAX 1000010 #define MAX 10000010 using namespace std; #define min(a,b) ((a) < (b) ? a:b) long long

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

最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 41168    Accepted Submission(s): 17992 Problem Description 在每年的校赛里.全部进入决赛的同学都会获得一件非常美丽的t-shirt.可是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的.所以如今他们想要寻

【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治

题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小.注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小).到达该点后按原路返回,然后往其他点走,直到所有点都走过. 可以知道,经过的边会构成一棵最短路径树.请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长