PAT甲级1003

算法与数据结构

采用无向图多重邻接表的存储结构。顶点结点表示城市,包括城市的第一条边,拥有的救援队数量,最短路径值,是否已经访问,最短路径的条数,最大救援队的数量。

迪杰斯特拉算法,做一点小小的增加就可以。对于多条路径的问题,比较新迭代操作计算的路径与源路径,如果小于源路径,就更改路径最短值,如果等于最短路径值,就增加路径的数量,新路径数量 = 源路径数量+当前前驱节点的路径数量。最大救援队是类似的,如果:
当前前驱节点最大救援队数量+当前节点救援队数量>当前节点最大救援队数量
就更改当前最大救援队数量。

代码

#include <iostream>
#include <memory.h>
#include <stack>
using namespace std;
typedef struct ARC{
    int c1, c2;
    int dis;
   struct ARC * next1;
   struct ARC * next2;
}ARC;
typedef struct CITY{
    int rescue;
    int roadnum;//距离源点的路径数量
    int maxrescue;
    int mindis;
    bool visit;
    ARC *firstarc;
}CITY;

void Dijkstra(int start, int desti, CITY *city, int citynum)
{
    /*vnum*/
    int vnum;
    vnum = 1;
    /*迭代一次的操作包括,计算新包括进来的值*/
    int newnode = start;
    city[start].maxrescue = city[start].rescue;
    city[start].roadnum = 1;
    int minestdis = 0;
    while(vnum<citynum && newnode != desti){
        city[newnode].visit = true;
        ARC * next = city[newnode].firstarc;
        int minnode;
        while(next){//在newnode的边中计算未包含进来的点的最短路径估计值
                int node, length;
                if(next->c1==newnode)   node = next->c2, length = next->dis, next = next->next1;
                else if(next->c2==newnode)   node = next->c1, length = next->dis, next = next->next2;
                if(city[node].visit == false){
                    if(city[node].mindis == 0 || city[node].mindis > city[newnode].mindis+length){
                        city[node].mindis  = city[newnode].mindis+length;
                        city[node].roadnum = city[newnode].roadnum;
                        city[node].maxrescue = city[newnode].maxrescue + city[node].rescue;
                    }
                    else if(city[node].mindis == city[newnode].mindis + length){//解决多条最短路径的问题
                        city[node].roadnum += city[newnode].roadnum;
                        if(city[node].maxrescue < city[newnode].maxrescue + city[node].rescue)
                            city[node].maxrescue = city[newnode].maxrescue + city[node].rescue;
                    }
                }
        }//end while
        minestdis  = 0;
        for(int j=0;j<citynum;j++){
            if(city[j].visit == false &&(minestdis == 0 || (city[j].mindis && city[j].mindis <= minestdis)) )
                minestdis = city[j].mindis, minnode = j;
        }
        newnode = minnode;//最小的那个点极为下一次迭代计算的源点
        vnum++;
    }
}

int main1003()
{
    int citynum, roadnum, start, desti;
    cin>>citynum>>roadnum>>start>>desti;
    CITY city[citynum];
    memset(city, 0, sizeof(CITY)*citynum);
    for(int i=0;i<citynum;i++){
        cin>>city[i].rescue;
    }
    for(int i=0;i<roadnum;i++){
        ARC *curarc = (ARC *)malloc(sizeof(ARC));
        cin>>curarc->c1>>curarc->c2>>curarc->dis;
        curarc->next1  = city[curarc->c1].firstarc;
        curarc->next2  = city[curarc->c2].firstarc;
        city[curarc->c1].firstarc = curarc;
        city[curarc->c2].firstarc = curarc;
    }
    Dijkstra(start, desti, city, citynum);
    cout<<city[desti].roadnum<<' '<<city[desti].maxrescue;
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值