题意
给出每个城市的点权,图的边权,要求找出最短路径的数量,和点权之和的最大值。
思路
dijkstra算法寻找最短路,用num_path数组记录最短路的数量。
(有错误的代码)
#include"bits/stdc++.h"
using namespace std;
const int maxn = 510;
int G[maxn][maxn]; int dis[maxn];
int w[maxn]; int weight_sum[maxn];
int vis[maxn]; int num_path[maxn];
int n, m, c1, c2;
struct Node {
bool operator()(int a, int b) {
return dis[a] >= dis[b];
}
};
void diskj(int startId) {
fill(dis, dis + maxn, INT32_MAX); fill(vis, vis + maxn, 0);
dis[startId] = 0; weight_sum[startId] = w[startId]; num_path[startId] = 1;
priority_queue<int, vector<int>, Node> q; q.push(startId);
for (int i = 0; i < n; ++i) {
int id;
while (true) {
if (q.empty()) {
return;
} else if (vis[q.top()]) {
q.pop();
continue;
}
id = q.top(); vis[id] = 1;
break;
}
for (int j = 0; j < n; ++j) {
if (vis[j] || G[j][id] == INT32_MAX) continue;
int ec = dis[id] + G[id][j], ew = weight_sum[id] + w[j];
if (ec < dis[j]) {
q.push(j);
dis[j] = ec; weight_sum[j] = ew;
num_path[j] = num_path[id];
} else if (ec == dis[j]) {
q.push(j);
weight_sum[j] = max(weight_sum[j],ew);
num_path[j] += num_path[id];
}
}
}
}
int main() {
fill(G[0], G[0] + maxn * maxn, INT32_MAX);
//freopen("input.txt", "r", stdin);
scanf("%d%d%d%d", &n, &m, &c1, &c2);
for (int i = 0; i < n; i++) scanf("%d", &w[i]);
for (int i = 0; i < m; i++) {
int id1, id2, L; scanf("%d%d%d", &id1, &id2, &L);
G[id1][id2] = G[id2][id1] = L;
}
diskj(c1);
cout << num_path[c2] << " " << weight_sum[c2] << endl;
}
Sample Input:
5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
Sample Output:
2 4
牛客网上面也有相同的题目,我把代码复制进去发现竟然没有通过,PAT网站上的明明已经ac了。发现是有路径没有探索到,说明我原来的代码是错误的。
修改之后ac:
#pragma GCC optimize(2)
#include"bits/stdc++.h"
using namespace std;
const int maxn = 510;
int G[maxn][maxn]; int dis[maxn];
int w[maxn]; int weight_sum[maxn];
int vis[maxn]; int num_path[maxn];
int n, m, c1, c2;
struct Node {
bool operator()(int a, int b) {
return dis[a] >= dis[b];
}
};
void diskj(int startId) {
fill(dis, dis + maxn, INT32_MAX); fill(vis, vis + maxn, 0);
dis[startId] = 0; weight_sum[startId] = w[startId]; num_path[startId] = 1;
priority_queue<int, vector<int>, Node> q; q.push(startId);
for (int i = 0; i < n; ++i) {
int id;
while (true) {
if (q.empty()) {
return;
} else if (vis[q.top()]) {
q.pop();
continue;
}
id = q.top(); vis[id] = 1;
break;
}
for (int j = 0; j < n; ++j) {
if (vis[j] || G[j][id] == INT32_MAX) continue;
int ec = dis[id] + G[id][j], ew = weight_sum[id] + w[j];
if (ec < dis[j]) {
dis[j] = ec; q.push(j); weight_sum[j] = ew;
num_path[j] = num_path[id];
} else if (ec == dis[j]) {
q.push(j);
weight_sum[j] = max(weight_sum[j],ew);
num_path[j] += num_path[id];
}
}
}
}
int main() {
fill(G[0], G[0] + maxn * maxn, INT32_MAX);
freopen("input.txt", "r", stdin);
scanf("%d%d%d%d", &n, &m, &c1, &c2);
for (int i = 0; i < n; i++) scanf("%d", &w[i]);
for (int i = 0; i < m; i++) {
int id1, id2, L; scanf("%d%d%d", &id1, &id2, &L);
G[id1][id2] = G[id2][id1] = L;
}
diskj(c1);
cout << num_path[c2] << " " << weight_sum[c2] << endl;
}
很郁闷,明明应该没问题的,检查很久之后发现竟然是两行的代码的顺序错了,导致优先队列失效。
不使用优先队列版本:
#include "bits/stdc++.h"
using namespace std;
const int N = 510;
int dis[N];
map<int,int> mp[N];
int vis[N];
int w[N];
vector<int> pre[N];
void dijkstra(int startId,int n){
fill(dis,dis+N,INT32_MAX);
dis[startId] = 0;
for (int i = 0; i < n; ++i) {
int id = -1; int min_d = INT32_MAX;
for(int j = 0;j < n;j++){
if (!vis[j] && dis[j] < min_d) id = j, min_d = dis[j];
}
if (id == -1) break;
vis[id] = 1;
for(auto& it:mp[id]) {
int eid = it.first;
if (vis[eid]) continue;
int ed = dis[id] + it.second;
if (ed < dis[eid]){
dis[eid] = ed;
pre[eid].clear();
pre[eid].push_back(id);
} else if (ed == dis[eid]) {
pre[eid].push_back(id);
}
}
}
}
int ans_w = 0, ans_cnt = 0;
vector<int> temp;
void dfs(int id,int endId){
temp.push_back(id);
if (id == endId){
ans_cnt ++;
int sum = 0;
for(int t:temp) sum += w[t];
ans_w = max(ans_w,sum);
}
for(int t:pre[id]) dfs(t,endId);
temp.pop_back();
}
int main(){
// freopen("input.txt","r",stdin);
int n, m, c1, c2 ; cin >> n >> m >> c1 >> c2;
for(int i=0;i<n;i++) scanf("%d",&w[i]);
for (int i = 0; i < m; ++i) {
int a,b,v; scanf("%d%d%d",&a,&b,&v);
mp[a][b] = mp[b][a] = v;
}
dijkstra(c1,n);
dfs(c2,c1);
cout << ans_cnt << " " << ans_w << endl;
}