题意是给定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;
}