PAT---- A1003 Emergency (25point(s))

题意

给出每个城市的点权,图的边权,要求找出最短路径的数量,和点权之和的最大值。

思路

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值