【PAT甲级】1003 Emergency 紧急情况

原题链接PTA | 程序设计类实验辅助教学平台 (pintia.cn)

Acwing链接1475. 紧急情况 - AcWing题库

 

分析

0.易错点

 for(int j = 0; j < n; j ++  )
        {
            if(dist[j] > dist[t] + g[t][j])
            {
                dist[j] = dist[t] + g[t][j];
                cnt[j] = cnt[t];
                //sum[j] += sum[t]; sum[j] +=  sum[t] + w[j];
                //  这样是错的,救援队的数量没有加上j点本身的救援队数量
                sum[j] = sum[t] + w[j]; // 这一步易出错 
            }
            else if(dist[j] == dist[t] + g[t][j])
            {
                cnt[j] += cnt[t];
                sum[j] = max(sum[j], sum[t] + w[j]);
            }
        }

1. 准备

const int N = 600;
int g[N][N], w[N]; // w[N]指权值, 这里是指每个点救援队的数量
int dist[N], cnt[N], sum[N]; //cnt[N] 最短路的数  sum[N]聚集到的救援队的最大数量
bool st[N];
int n, m, Start, End;// 点数 边数 当前救援起点城市编号   发出救援信号的城市编号

2. 核心

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    
    dist[Start] = 0, cnt[Start] = 1, sum[Start] = w[Start];
    // dist[S] 起点到起点的距离为 0 
    // cnt[S] = 1 题目数据保证 C1 和 C2 之间至少存在一条路径相连。
    //  sum[S] = w[S] 最大救援队数量 
    // 这里救援队还没出发去其他城市 所以救援队数量只有S号城市的救援队
    
    for(int i = 0; i < n; i ++)
    {
        int t = -1;
        for(int j = 0; j < n; j ++ )
        {
            if(st[j] == false && (t == -1 || dist[t] > dist[j]) )  t = j;
        }
        
        st[t] = true;
        
        // 用t 更新每个点到起点的距离 
        for(int j = 0; j < n;  j ++ ) // j 从0 开始 因为城市编号是从0开始的
        {
            if(dist[j] > dist[t] + g[t][j]) //从t点中转  j 先到t  t再到起点 
            {
                dist[j] = dist[t] + g[t][j];
                cnt[j] = cnt[t];
                sum[j] = sum[t] + w[j]; 
                // 从t点中转时 总的救援队数量 sum[t] + j点的救援队数量
            }
            //从j点到起点的距离  和  从j到t再到起点的距离相等 
            else if(dist[j] == dist[t] + g[t][j]) 
            {
                cnt[j] += cnt[t]; // 最短路的个数
                // 比较 到底是j点救援队数量多 还是 j到t中转再到起点时 救援队数量多
                sum[j] = max(sum[j], sum[t] + w[j]); 
            }    
        }
        
        
    }
}

3. main函数

int main()
{
    memset(g, 0x3f, sizeof g);
    
    cin >> n >> m >> Start >> End; // 输入
    
    for(int i =  0; i < n; i ++ )
    {
        cin >> w[i]; // 输入权值——即每个点的救援队数量
    }
    
    while(m -- ) // m条边 所以次个输入
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b], c); // 邻接矩阵构造无向图
    }

    dijkstra();
    
    cout << cnt[End] << ' ' << sum[End]; // 输出最短路数量   最大救援队数量
    
    return 0;

}

4. AC代码

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 600;

int g[N][N]; 
int dist[N], cnt[N], sum[N], w[N]; 
int n, m, Start, End; 
bool st[N]; 

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    
    dist[Start] = 0,      cnt[Start] = 1,   sum[Start] = w[Start];

    for(int i = 0; i < n; i ++ )
    {
        int t = -1;
        
        for(int j = 0; j < n; j ++ )
        {
            if(st[j] == false && (t == -1 || dist[t] > dist[j]) )
                t = j;
        }
        
        st[t] = true;
        
        
        for(int j = 0; j < n; j ++  )
        {
            if(dist[j] > dist[t] + g[t][j])
            {
                dist[j] = dist[t] + g[t][j];
                cnt[j] = cnt[t];
                sum[j] = sum[t] + w[j];
            }
            else if(dist[j] == dist[t] + g[t][j])
            {
                cnt[j] += cnt[t];
                sum[j] = max(sum[j], sum[t] + w[j]);
            }
        }
        
    }
    
}


int main()
{
    memset(g, 0x3f, sizeof g);
    
    cin >> n >> m >> Start >> End; 
    
    for(int i =  0; i < n; i ++ )
    {
        cin >> w[i]; 
    }
    
    while(m -- ) 
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b], c); 
    }

    dijkstra();
    
    cout << cnt[End] << ' ' << sum[End];
    
    return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值