PAT甲级1003 Emergency(最短路)

题意是给定n个城市m条道路,每个城市有权重p,求城市c1到c2最短路径的条数,以及最短路径经过城市的权重和的最大值。既然要求最短路,就祭上了dijkstra,只不过需要对算法做一定的修改,需要在更新最短路时,同时更新最短路条数与最大权重。

具体的更新策略如下(u为当前道路的起点,v为当前道路的终点):

①当dis[v.x] > dis[u.x]+v.d时

  • 更新最短路dis[v.x] = dis[u.x]+v.d
  • 更新最短路径数path_cnt[v.x] = path_cnt[u.x](因为从起始点c1到点u有path_cnt[u.x]条最短路,且经过当前道路u->v是c1到v的最短路,所以抵达v的最短路条数等于抵达u的最短路条数)
  • 更新最大权重p_sum[v.x] = p_sum[u.x]+p[v.x],u的最大权重加v的权重就是v的最大权重

②当dis[v.x] == dis[u.x]+v.d时

  • 更新最短路径数path_cnt[v.x] += path_cnt[u.x],在未经过u的路径上抵达v有path_cnt[v.x]条最短路,而抵达u有path_cnt[u.x]条最短路,所以抵达v的当前总的最短路为path_cnt[v.x] += path_cnt[u.x]
  • 更新最大权重p_sum[v.x] = max(p_sum[v.x], p_sum[u.x]+p[v.x])

最后输出时,c1到c2的最短路数为path_cnt[c2],最大权重为p_sum[c2]+p[c1](因为我嫌麻烦没有把p_sum全部初始化为p[c1]...先把p_sum初始化了也是可以的)

然后就是要吐槽一下PAT的评测姬,next是保留字,不能使用...

#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e4;
struct node
{
    int x, d;
    node() {}
    node(int X, int D):x(X), d(D) {}
    bool operator < (const node &a) const
    {
        if(d == a.d)
            return x < a.x;
        return d > a.d;
    }
};
vector<node> Next[maxn]; //邻接表
int n, m, c1, c2, p[maxn]; //p记录每个城市的人数
int dis[maxn], path_cnt[maxn], p_sum[maxn];
//最短路,到达城市i的最短路径数目,到达城市i最短路径中的最大救援人数
int ans_cnt, ans_amt; //到达目标城市的最短路条数,最短路中的最大救援人数

void dijkstra(int s)
{
    int vis[maxn] = {0};
    memset(dis, INF, sizeof(dis));
    dis[s] = 0;
    path_cnt[s] = 1;
    priority_queue <node> q;
    q.push(node(s, dis[s]));

    while(!q.empty())
    {
        node u = q.top();
        q.pop();
        if(vis[u.x]) continue;
        for(int i = 0; i < Next[u.x].size(); ++i)
        {
            node v = Next[u.x][i];
            if(dis[v.x] > dis[u.x]+v.d)
            {
                dis[v.x] = dis[u.x]+v.d;
                path_cnt[v.x] = path_cnt[u.x];
                p_sum[v.x] = p_sum[u.x]+p[v.x];
                q.push(node(v.x, dis[v.x]));
            }
            else if(dis[v.x] == dis[u.x]+v.d)
            {
                path_cnt[v.x] += path_cnt[u.x];
                p_sum[v.x] = max(p_sum[v.x], p_sum[u.x]+p[v.x]);
            }
        }
        vis[u.x] = 1;
    }
}

void read()
{
    cin >> n >> m >> c1 >> c2;
    for(int i = 0; i < n; ++i)
        cin >> p[i];
    for(int i = 0; i < m; ++i)
    {
        int u, v, l;
        cin >> u >> v >> l;
        Next[u].push_back(node(v, l));
        Next[v].push_back(node(u, l));
    }
}

void solve()
{
    dijkstra(c1);
    ans_cnt = path_cnt[c2];
    ans_amt = p_sum[c2]+p[c1];
    cout << ans_cnt << ' ' << ans_amt;
}

int main()
{
	read();
	solve();
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值