優先隊列:二元堆積最佳化的Prim與Dijkstra演算法

來源:互聯網
上載者:User

終於調出來了,理解之後其實很簡單,但是一些細節總是沒處理好。直到現在還有一點疑問在。

兩者的漸進複雜度都是O(ELogV+VLogV),因為邊調整了E次,刪除最小元V次,二元堆積的操作都是LogV層級的。

事實上兩個演算法很相似,Prim只是鬆弛操作和Dijksrra還有記錄ans的方式不同。

在演算法導論上看到,Kruskal演算法是ELogE的即可以約成E*2LogV即ELogV,漸進意義上是和Prim一樣的。

平時很少看見用heap最佳化的Prim和Dijkstra,可能是因為Kruskal和SPFA有更好的表現或編程複雜度小點吧,當然也看到不少C++用STL的優先隊列寫的Prim/Dijkstra。

下面是POJ 2387和1287的代碼,分別對應Dijkstra和Prim演算法。

/*    很裸很水的最短路,練習二元堆積最佳化的Dijstra~    之前二元堆積最佳化的Prim敲了好幾遍前後花了不下八個小時調試還是沒有調試成功,    但是還好,熟悉了優先隊列的操作。    十幾天后的今天重新想起這個,終於調出來了堆最佳化的Dijstra。理解之後還是蠻簡單的。    一些寫法並不是最優的,例如heap的實現中可以減少交換元素等。但是有這個自己寫的AC    過的Dijkstra在,以後寫二元堆積最佳化的Prim/Dijkstra和其它優先隊列的題目就可以拿它對照著Debug了。    2011-07-24 23:00*/#include <stdio.h>#define MAXN 1200#define MAXM 1200000#define INF 19930317struct node{    int d, v, p;}heap[MAXN];int pos[MAXN], hl;int e[MAXM], cost[MAXM], next[MAXM], g[MAXN], size;int m, n, s, t;void insert(int u, int v, int w){    e[++size] = v;    next[size] = g[u];    cost[size] = w;    g[u] = size;}void swap(int a, int b){    heap[0] = heap[a];    heap[a] = heap[b];    heap[b] = heap[0];    pos[heap[a].v] = a;    pos[heap[b].v] = b;}void heapfy(){    int i = 2;    while (i <= hl)    {        if ((i < hl) && (heap[i + 1].d < heap[i].d))            i++;        if (heap[i].d < heap[i >> 1].d)        {            swap(i, i >> 1);            i <<= 1;        }        else            break;    }}void decrease(int i){    while ((i != 1) && (heap[i].d < heap[i >> 1].d))    {        swap(i, i >> 1);        i >>= 1;    }}void relax(int u ,int v, int w){    if (w + heap[pos[u]].d < heap[pos[v]].d)    {        heap[pos[v]].p = u;        heap[pos[v]].d = w + heap[pos[u]].d;        decrease(pos[v]);    }}void delete_min(){    swap(1, hl);    hl--;    heapfy();}void init(){    int u ,v ,w, i;    scanf("%d%d", &m, &n);    for (i = 1; i <= m; i++)    {        scanf("%d%d%d", &u, &v, &w);        insert(u, v, w);        insert(v, u, w);    }    s = 1;    t = n;}int dijkstra(){    int u, p, i;    for (i = 1; i <= n; i++)    {        heap[i].v = pos[i] = i;        heap[i].d = INF;    }    heap[s].p = s;    heap[s].d = 0;    swap(1, s);    hl = n;    while (hl)    {        u = heap[1].v;        delete_min();        p = g[u];        while (p)        {            if (pos[e[p]] <= hl)                relax(u, e[p], cost[p]);            p = next[p];        }    }}int main(){    init();    dijkstra();    printf("%d\n", heap[pos[t]].d);    return 0;}

 

 

 

/*    二元堆積最佳化的Prim,相比Dijkstra只有鬆弛操作不同    很鬱悶的是heapfy函數,就是從堆頂往下篩,仿照別人的寫法AC了,自己寫的迭代以減少    交換次數的在範例的一個資料陷入死迴圈了,而仿照資料結構與演算法分析寫的WA了。    以前沒寫過帶有pos作為優先隊列的heap這樣調整,所以也不知道哪錯了。    下面是強大的範例:5 71 2 52 3 72 4 84 5 113 5 101 5 64 2 12    有空調調吧。    2011-07-25 09:32*/#include <stdio.h>#define MAXN 1200#define MAXM 120000#define INF 19930317int e[MAXM], cost[MAXM], next[MAXM], g[MAXN], size;struct node{    int d, v;}heap[MAXN];int pos[MAXN], hl;int m, n;void swap(int a, int b){    heap[0] = heap[a];    heap[a] = heap[b];    heap[b] = heap[0];    pos[heap[a].v] = a;    pos[heap[b].v] = b;}void heapfy(){    int i = 2;    while (i <= hl)    {        if ((i < hl) && (heap[i + 1].d < heap[i].d))            i++;        if (heap[i].d < heap[i >> 1].d)        {            swap(i, i >> 1);            i <<= 1;        }        else            break;    }}/*void heapfy(){    int i = 1, j = 2;    heap[0] = heap[1];    while (j <= hl)    {        if ((j < hl) && (heap[j].d > heap[j+1].d))            j++;        if (heap[j].d < heap[0].d)        {            heap[i] = heap[j];            pos[heap[i].v] = i;            i = j;            j >>= 1;        }        else            break;    }    heap[i] = heap[0];    pos[heap[i].v] = i;}void heapfy(){    int i, j;    heap[0] = heap[1];    for (i = 1; i * 2 <= hl; i = j)    {        j = i * 2;        if (j < hl && heap[j+1].d < heap[j].d)            j++;        if (heap[0].d > heap[j].d)        {            heap[i] = heap[j];            pos[heap[i].v] = i;        }    }    heap[i] = heap[0];    pos[heap[i].v] = i;}*/void decrease(int i){    heap[0] = heap[i];    while ((i > 1) && (heap[0].d < heap[i >> 1].d))    {        heap[i] = heap[i >> 1];        pos[heap[i].v] = i;        i >>= 1;    }    heap[i] = heap[0];    pos[heap[i].v] = i;}void delete_min(){    swap(1, hl);    hl--;    heapfy();}void relax(int v, int w){    if (w < heap[pos[v]].d)    {        heap[pos[v]].d = w;        decrease(pos[v]);    }}void insert(int u, int v, int w){    e[++size] = v;    cost[size] = w;    next[size] = g[u];    g[u] = size;}void init(){    int i, u, v, w;    size = 0;    memset(g, 0, sizeof(g));    for (i = 1; i <= m; i++)    {        scanf("%d%d%d", &u, &v, &w);        insert(u, v, w);        insert(v, u, w);    }}int prim(){    int mst = 0, u , p, i;    for (i = 1; i <= n; i++)    {        pos[i] = heap[i].v = i;        heap[i].d = INF;    }    heap[1].d = 0;    hl = n;    while (hl)    {        u = heap[1].v;        mst += heap[1].d;        delete_min();        for (p = g[u]; p; p = next[p])            if (pos[e[p]] <= hl)                relax(e[p], cost[p]);    }    return mst;}int main(){    while (scanf("%d%d", &n, &m) == 2 && n)    {        init();        printf("%d\n", prim());    }}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.