最小堆实现优先队列+Dijkstra 解决最短路问题

某著名游戏公司上机题目

题目回来网上搜了一把是这样的
BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed shared memory machine with a hierarchical communication subsystem. Valentine McKee’s research advisor, Jack Swigert, has asked her to benchmark the new system.
Since the Apollo is a distributed shared memory machine, memory access and communication times are not uniform,'' Valentine told Swigert.Communication is fast between processors that share the same memory subsystem, but it is slower between processors that are not on the same subsystem. Communication between the Apollo and machines in our lab is slower yet.”

“How is Apollo’s port of the Message Passing Interface (MPI) working out?” Swigert asked.

Not so well,'' Valentine replied.To do a broadcast of a message from one processor to all the other n-1 processors, they just do a sequence of n-1 sends. That really serializes things and kills the performance.”

“Is there anything you can do to fix that?”

Yes,'' smiled Valentine.There is. Once the first processor has sent the message to another, those two can then send messages to two other hosts at the same time. Then there will be four hosts that can send, and so on.”

“Ah, so you can do the broadcast as a binary tree!”

“Not really a binary tree – there are some particular features of our network that we should exploit. The interface cards we have allow each processor to simultaneously send messages to any number of the other processors connected to it. However, the messages don’t necessarily arrive at the destinations at the same time – there is a communication cost involved. In general, we need to take into account the communication costs for each link in our network topologies and plan accordingly to minimize the total time required to do a broadcast.”

Input
  The input will describe the topology of a network connecting n processors. The first line of the input will be n, the number of processors, such that 1 <= n <= 100.

The rest of the input defines an adjacency matrix, A. The adjacency matrix is square and of size n x n. Each of its entries will be either an integer or the character x. The value of A(i,j) indicates the expense of sending a message directly from node i to node j. A value of x for A(i,j) indicates that a message cannot be sent directly from node i to node j.

Note that for a node to send a message to itself does not require network communication, so A(i,i) = 0 for 1 <= i <= n. Also, you may assume that the network is undirected (messages can go in either direction with equal overhead), so that A(i,j) = A(j,i). Thus only the entries on the (strictly) lower triangular portion of A will be supplied.

The input to your program will be the lower triangular section of A. That is, the second line of input will contain one entry, A(2,1). The next line will contain two entries, A(3,1) and A(3,2), and so on.

Output
  Your program should output the minimum communication time required to broadcast a message from the first processor to all the other processors.

Sample Input

5
50
30 5
100 20 50
10 x x 10

Sample Output

35

这是一个巨坑的题目,猛一看我以为是一道最小生成树,当即写下克鲁斯卡尔算法,并使用链表优化存储,手写快速排序,写完正想提交,发现样例过不去,巨坑巨坑,然后回过头来重新理解题意,理解有十分钟,原来是个最短路的最大值问题,有点绕哈,因为一开始信息传递点是四处传递信息的,最快通知到所有地点,当然需要到达每个地方都求出一条最短的路径,最快的时间传递到每个地方,取决的最短路的那个最大值 。要求不许使用c++,只能使用c语言,且是你认为的最快效率,我大概知道要自己维护一个最小堆来取代c++里面的优先队列从而把迪杰斯特拉算法每次求离源点最近的那条路线的时间复杂度给省去,由于时间关系我还是简单的写了一下迪杰斯特拉算法的通用解法n方的复杂度,跟面试官解释了一下,反正给不给下一轮面试机会就看命了,回来后补上最优解,,代码如下:如下最小堆的维护较为难理解,可百度搜索学习一下。

//题目理解:求城市1到各个城市最短路径的最大值
//思路:dijkstra+辅助堆,辅助堆用来选取当前到城市1距离最小的那个城市。
//这里采用了最小堆来实现。用最小堆保存图中所有顶点到源点的距离
#include <string.h>
#include <stdio.h>

#define MAX_CITY 101
#define MAX_EDGE 5000
#define INF 0x7fffffff

struct city
{
    int pTimeCost;//最短花费时间
    int pCity_index;//城市编号
    int pCity_start;//起点
}Minheap[MAX_CITY];//小根堆

int pos[MAX_CITY];//存储改变位置后的编号为xxx的节点对应在堆中的位置
int Minheapelement_count;

//存输入信息,Citya城市传到cityb的时间
int cityb[MAX_EDGE];//记录cityb
int Timecost[MAX_EDGE];//时间开销
int nextCity[MAX_EDGE];
int preCity[MAX_EDGE];
int pCityCount;

int City_Count;

//录入信息
void insert(int Cityend, int Citystart, int PtimeCost)
{
    cityb[++pCityCount] = Citystart;
    nextCity[pCityCount] = preCity[Cityend];
    Timecost[pCityCount] = PtimeCost;
    preCity[Cityend] = pCityCount;
}

//调整堆元素
void swap(int a, int b)
{
    Minheap[0] = Minheap[a];
    Minheap[a] = Minheap[b];
    Minheap[b] = Minheap[0];
    pos[Minheap[a].pCity_index] = a;
    pos[Minheap[b].pCity_index] = b;
}

//对于某个节点的value小于左右儿子的最大值需要调整以满足最小堆的性质
void siftdown()
{
    int i = 2;
    while (i <= Minheapelement_count) {
        if ((i < Minheapelement_count) && (Minheap[i + 1].pTimeCost < Minheap[i].pTimeCost)) {
            i++;
        }
        if (Minheap[i].pTimeCost < Minheap[i >> 1].pTimeCost) {
            swap(i, i >> 1);
            i <<= 1;
        }
        else {
            break;
        }
    }
}

//在堆中,对于某个非1的节点,value大于父节点的value需要调整以满足最小堆的性质
void siftup(int i)
{
    while ((i != 1) && (Minheap[i].pTimeCost < Minheap[i >> 1].pTimeCost)) {
        swap(i, i >> 1);
        i >>= 1;
    }
}

void UpdateTimeCost(int u ,int v, int w)
{
    if (w + Minheap[pos[u]].pTimeCost < Minheap[pos[v]].pTimeCost) {
        Minheap[pos[v]].pCity_start = u;
        Minheap[pos[v]].pTimeCost = w + Minheap[pos[u]].pTimeCost;
        //printf("heap[pos[v]].d: %d\n", heap[pos[v]].d);
        siftup(pos[v]);//把更新后的数据项移到堆中中适合他的位置
    }
}

//处理输入字符串数据
int Dealdata(char* s)
{
    int lens = strlen(s);
    int resul = 0;
    if (s[0] == 'x') {
        return -1;
    }

    else {
        for(int i = 0; i < lens; i++) {
            if(s[i] >= '0' && '9' >= s[i]) {
                resul = resul * 10 + s[i] - '0';
            }
            else {
                return -1;
            }
        }
    }
    return resul;
}

//利用当前堆最短路径去更新已保存的最短路径后删除该堆数据,并调整以满足最小堆的性质
void delete_min()
{
    swap(1, Minheapelement_count);
    Minheapelement_count--;
    siftdown();
}

void init()
{
    int u ,v ,w, i;
    scanf("%d", &City_Count);
    for (i = 2; i <= City_Count; i++) {
        for (int j = 1; j<= i-1; j++){
            char str[15];
            scanf("%s", str);
            int pTimeCostTmp = Dealdata(str);
            //printf("ppp:%d\n", ppp);
            if (pTimeCostTmp > 0) {
                insert(i, j, pTimeCostTmp);
                insert(j, i, pTimeCostTmp);
            }
        }
    }
}


void dijkstra()
{
    int u, p, i;
    //初始化最小堆
    for (i = 1; i <= City_Count; i++) {
        Minheap[i].pCity_index = pos[i] = i;
        Minheap[i].pTimeCost = INF;
    }
    Minheap[1].pCity_start = 1;
    Minheap[1].pTimeCost = 0;
    Minheapelement_count = City_Count;
    while (Minheapelement_count)
    {
        u = Minheap[1].pCity_index;
        delete_min();
        p = preCity[u];
        while (p) {
            if (pos[cityb[p]] <= Minheapelement_count) {
                UpdateTimeCost(u, cityb[p], Timecost[p]);//更新最短value
            }
            p = nextCity[p];
        }

    }
}

int main()
{
    init();
    dijkstra();
    int maxn = -1;
    //求单源最短路径的最大值
    for (int i = 1; i <= City_Count; i++) {
        if (maxn < Minheap[pos[i]].pTimeCost) {
            maxn = Minheap[pos[i]].pTimeCost;
        }
    }
    printf("%d\n", maxn);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

breakpoints_

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值