PAT----A1087 All Roads Lead to Rome (30point(s))

A1087 All Roads Lead to Rome (30point(s))

题意

找出花费最小并且获得最大幸福度的路径,如果不唯一则选择最短的。

思路

考察dijskra算法,这里用了优先队列。
Sample Input:

6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1

Sample Output:

3 3 195 97
HZH->PRS->ROM
#include "bits/stdc++.h"
using namespace std;
const int N = 210;
vector<int> links[N];
int vis[N];
int G[N][N];
int dis[N];
int w[N];
vector<int> pre[N];


struct cmp{
    bool operator()(int id1,int id2){
        return dis[id1] >= dis[id2];
    }
};
void dsijk(int startId,int n){
    fill(dis,dis+N,INT32_MAX);
    dis[startId] = 0;
    fill(vis,vis+N,0);

    priority_queue<int,vector<int>,cmp> 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(), q.pop();
            break;
        }
        vis[id] = 1;
        for (int j = 0; j < n; ++j) { // for all node
            if (vis[j] || G[id][j] == INT32_MAX) continue;
            int ed = dis[id] + G[id][j];
            if (ed < dis[j]){
                dis[j] = ed, q.push(j);
                pre[j].clear(), pre[j].push_back(id);
            } else if (ed == dis[j]){
                q.push(j), pre[j].push_back(id);
            }
        }
    }
}

vector<int> temp,ans;
int ans_w = 0;
int cnt_lessPath = 0;
void dfs(int id,int eid){
    if (id == eid){
        cnt_lessPath ++;
        temp.push_back(id);
        int sum = 0;
        for(int t:temp) sum += w[t];

        if( ans.empty()
        ||  sum > ans_w
        || (sum == ans_w && temp.size() < ans.size())) {
            ans = temp;
            ans_w = sum;
        }
        temp.pop_back();
        return;
    }
    temp.push_back(id);
    for(int t:pre[id]) dfs(t,eid);
    temp.pop_back();
}
int main(){
//     freopen("input.txt","r",stdin);
    int n, k; cin >> n >> k;
    vector<string> names(n);
    unordered_map<string,int> name2Id;
    for (int i = 0; i < n; ++i) {
        cin >> names[i];
        name2Id[names[i]] = i;
        if (i) scanf("%d",&w[i]);
    }
    fill(G[0],G[0]+N*N,INT32_MAX);
    for (int i = 0; i < k; ++i) {
        string s1,s2; int v;
        cin >> s1 >> s2 >> v;
        G[name2Id[s1]][name2Id[s2]] = G[name2Id[s2]][name2Id[s1]] = v;
    }
    int startId = 0; int endId = name2Id["ROM"];
    dsijk(startId,n);
    dfs(endId,startId);
    cout << cnt_lessPath << " " << dis[endId] << " " << ans_w << " " << (int)ans_w/(ans.size()-1) << endl;
    reverse(ans.begin(),ans.end());
    for (int i = 0; i < ans.size(); ++i) {
        cout << names[ans[i]];
        if (i != ans.size()-1) printf("->");
        else printf("\n");
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值