Node:最短路径之Dijkstra堆优化

来源:互联网 发布:bluestack for mac 编辑:程序博客网 时间:2024/06/05 05:53
#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>#include <stack>#include <queue>#define flush(arr,i) memset(arr,i,sizeof(arr))#define INF 0xfffffffusing namespace std;const int maxn=1010;//到节点的距离和第i个节点的前一个节点int dis[maxn], pre[maxn];//边集int cost[maxn][maxn];//是否在集合之中bool vis[maxn];struct Node{    int nodeId;    int len;};Node heap[maxn];int n, m, s, sz;/*测试数据---------8 14 66 5 16 4 36 7 65 3 35 4 17 4 17 2 44 2 93 4 13 1 41 2 17 8 142 8 23 2 2--------*///数据录入和初始化void initMap(){    //没有进入集合    flush(vis, 0);    sz = 0;    scanf("%d%d%d", &n, &m, &s);    int from, to, len;    for(int i = 1; i <= n; i++)    {        dis[i] = INF;        pre[i] = 0;        for(int j = 1; j <= n; j++)            cost[i][j] = INF;    }    for(int i = 0; i < m; i++)    {        scanf("%d%d%d",&from, &to, &len);        printf("%c %c %d\n",from + 'r', to + 'r', len);        cost[from][to] = cost[to][from] = len;    }}//路径输出void showPath(int cur){    if(pre[cur])        showPath(pre[cur]);    printf("->%c", cur + 'r');}/*//优化集中在这一部分int getMinmunNode(){    int maxCost = INF, pos = -1;    for(int i = 1; i <= n; i++)        if(!vis[i] && dis[i] < maxCost)        {            pos = i;            maxCost = dis[i];        }    //加入集合标记为1    vis[pos] = 1;    return pos;}*///--------------------------------------------------//使用堆来进行优化:(用数组进行维护)堆从下标1开始int getMinmNode()         //最小堆{    int ret = heap[1].nodeId;    //,第一个节点删除,最后一个放到第一个位置,之后向下调整    heap[1] = heap[sz--];    int cur = 1, son = 2;    //  存在儿子比父亲小    while(son <= sz && (heap[son].len < heap[cur].len || heap[son+1].len < heap[cur].len))    {        if(heap[son].len > heap[son+1].len)            son++;        swap(heap[son].len,heap[cur].len);        swap(heap[son].nodeId,heap[cur].nodeId);        //指针下移        cur = son;        son*= 2;    }    return ret;}void deleteNode(int id){    int pos = -1;    for(int i = 0; i < sz; i++)        if(heap[i].nodeId == id)    {        pos = i;        break;    }    if(pos != -1)    {        for(int i = pos; i < sz - 1; i++)            heap[i] = heap[i + 1];        sz--;    }}void insertNode(Node t){    //添加到最后一个节点,向上调整    heap[++sz] = t;    int cur = sz, p = cur/2;    while(p>=1)    {        //比父亲小的节点        if(heap[cur].len < heap[p].len)        {            swap(heap[cur].len,heap[p].len);            swap(heap[cur].nodeId,heap[p].nodeId);        }        cur = p;        p = cur/2;    }}//----------------------------------------------------void Dijkstra(int s){    dis[s] = 0;    Node from;    from.len = 0;    from.nodeId = s;    insertNode(from);    //一共更新n次    while(sz)    {        //获取当前的is最小节点进行下一步更新        int cur = getMinmNode();        //输出当前选出的节点        printf("cur %c\n", cur + 'r');        for(int j = 0; j <= n; j++)            //满足更新条件            if(dis[j] > dis[cur] + cost[cur][j])        {            dis[j] = dis[cur] + cost[cur][j];            deleteNode(j);            Node newNode;            newNode.len = dis[j];            newNode.nodeId = j;            insertNode(newNode);            //维护路径            pre[j] = cur;            //输出更新情况            printf("%c->%c:%d ", s + 'r', j + 'r', dis[j]);        }        printf("\n");    }    for(int i = 1; i <= n; i++)    {        showPath(i);        printf(" %d\n",dis[i]);    }}int main(){    freopen("data.txt","r",stdin);    initMap();    Dijkstra(s);    return 0;}

0 0