【PAT】1003. Emergency (25)

1. 题目地址:http://www.patest.cn/contests/pat-a-practise/1003

2.分析:

本题要求输出特定俩点间最短路径的条数和最短路径中能call up的最多救援队数。
由特定俩点间的最短路径易想到dijkstra算法,但原始的dijkstra算法只能求出特定俩点间的最短距离,无法求出最短路径的条数等其它信息。这里我们应用了dijkstra算法的思想,但在计算的过程中我们记录路径距离相应的条数及相应的最多救援队数。

3. 代码:


#include <stdio.h>

using namespace std;

int main()
{

//从文本输入数据:
//#ifndef ONLINE_JUDGE
//  freopen("in.txt","r",stdin);
//#endif

    int n,m,s,d;//城市数,路径数,原点,目的点
    int teams[500];//救援队
    int G[500][500];//图

    struct E
    {
        int dis;//距原点的距离
        int num;//原点到该点为此距离的条数
        int maxTeams;//该距离下原点可call up至此点的最大救援队数
    };
    struct E edge[500];//与原点间的距离等相应的信息

    scanf("%d%d%d%d",&n,&m,&s,&d);

        for(int i=0;i<n;++i){
            int iTmp;
            scanf("%d",&iTmp);
            teams[i] = iTmp;
        }
        //初始化图信息
        for(int j=0;j<n;++j){
            for(int k = 0;k<n;++k){
                G[j][k]= -1;//距离为无穷远
            }
            G[j][j]=0;
        }
        int c1,c2,L;
        for(int i=0;i<m;++i){
            scanf("%d%d%d",&c1,&c2,&L);
            G[c1][c2]=L;
            G[c2][c1]=L;
        }

        for(int i=0;i<n;++i){
            edge[i].dis=-1;
            edge[i].num=0;
            edge[i].maxTeams=0;
        }

        bool mark[500]={0};//点是否被选取,初始化为未被选取
        int newP=s;
        edge[s].dis = 0;
        edge[s].num = 1;
        edge[s].maxTeams = teams[s];
        mark[newP]=true;//点newP已被选
        int num = n-1;//依次选取距离最小的n-1个点
        int newDis;
        while(num--){
            for(int j=0;j<n;++j){//更新与newP点相连的点的edge信息
                if(mark[j])
                    continue;
                if(G[newP][j] == -1)
                    continue;
                newDis = edge[newP].dis + G[newP][j];
                if(edge[j].dis == newDis){//发现距离相同的路径
                    edge[j].num += edge[newP].num;//路径数相加
                    if((edge[newP].maxTeams + teams[j]) > edge[j].maxTeams)//最大救援队数为距离相同的路径中救援队数较大的
                        edge[j].maxTeams = edge[newP].maxTeams + teams[j];
                }else if(edge[j].dis == -1 || edge[j].dis > newDis){//发现更小的距离,进行更新
                    edge[j].dis = newDis;
                    edge[j].num = edge[newP].num;
                    edge[j].maxTeams = edge[newP].maxTeams + teams[j];
                }
            }
            int min = 123123123;
            for(int k = 0;k<n;++k){//选取距离最小的点
                if(mark[k])
                    continue;
                if(edge[k].dis == -1)
                    continue;
                if(edge[k].dis < min){
                    min = edge[k].dis;
                    newP = k;
                }
            }
            mark[newP] = true;
            if(newP == d)//到目的点的距离等相应的信息已找到,则结束
                break;
        }
        printf("%d %d\n",edge[d].num,edge[d].maxTeams);
        return 0;
//关闭输入文本
//#ifndef ONLINE_JUDGE
//      fclose(stdin);
//#endif
}

时间复杂度:O(n^2)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值