Skip to content

1087 All Roads Lead to Rome

Statement

Metadata

  • 作者: CHEN, Yue
  • 单位: 浙江大学
  • 代码长度限制: 16 KB
  • 时间限制: 200 ms
  • 内存限制: 64 MB

Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness.

Input Specification

Each input file contains one test case. For each case, the first line contains 2 positive integers N (2\le N\le 200), the number of cities, and K, the total number of routes between pairs of cities; followed by the name of the starting city. The next N-1 lines each gives the name of a city and an integer that represents the happiness one can gain from that city, except the starting city. Then K lines follow, each describes a route between two cities in the format City1 City2 Cost. Here the name of a city is a string of 3 capital English letters, and the destination is always ROM which represents Rome.

Output Specification

For each test case, we are supposed to find the route with the least cost. If such a route is not unique, the one with the maximum happiness will be recommanded. If such a route is still not unique, then we output the one with the maximum average happiness – it is guaranteed by the judge that such a solution exists and is unique.

Hence in the first line of output, you must print 4 numbers: the number of different routes with the least cost, the cost, the happiness, and the average happiness (take the integer part only) of the recommanded route. Then in the next line, you are supposed to print the route in the format City1->City2->...->ROM.

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

Tutorial

题意:

给出一张无向图,给出起点,终点固定,每个点(除了起点)有点权,每条边有边权,找一条最短路径,依次满足如下三个条件:

  • 首先满足边权和最小。
  • 其次满足路径上经过的所有点的点权和最大。
  • 最后满足经过的点数最少。

另外还要求边权和最小的不同路径条数,和上述路径的路径上的点。

注意:第三个条件,题目本身给出的实际上点权和的平均值最大。

思路:

Dijkstra 套路了,只不过转移过程中维护的变量多了点,顺便记录下方案和前驱结点即可。

Solution

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define SZ(x) (int(x.size()))
using pII = pair<int, int>;
const int N = 1e3 + 10, INF = 0x3f3f3f3f;
map<string, int> mp;
int n, m, w[N], pre[N];
string st, ed, fmp[N];

vector<vector<pII> > G;

int getID(const string &s) {
    static int cnt = 0;
    if (mp.count(s) == 0) {
        mp[s] = ++cnt;
        fmp[cnt] = s;
    }
    return mp[s];
}

struct valde {
    int cost, w, num;
    valde() {}
    valde(int cost, int w, int num) : cost(cost), w(w), num(num) {}
    bool operator<(const valde &other) const {
        if (cost != other.cost)
            return cost < other.cost;
        if (w != other.w)
            return w > other.w;
        if (num != other.num)
            return num < other.num;
        return false;
    }
};

struct node {
    int to;
    valde val;
    node() {}
    node(int to, valde val) : to(to), val(val) {}
    bool operator<(const node &other) const {
        return !(val < other.val);
    }
};

valde dis[N];
bool vis[N];
int f[N];

void gao(int st) {
    for (int i = 1; i <= n; ++i) {
        dis[i] = valde(INF, w[i], 1);
        vis[i] = 0;
        f[i] = 0;
    }
    dis[st] = valde(0, w[st], 1);
    priority_queue<node> pq;
    pq.push(node(st, dis[st]));
    pre[st] = -1;
    f[st] = 1;
    while (!pq.empty()) {
        node u = pq.top();
        pq.pop();
        if (vis[u.to])
            continue;
        //		cout << u.to << " " << f[u.to] << endl;
        vis[u.to] = 1;
        for (auto &it : G[u.to]) {
            int v = it.fi, cost = it.se;
            valde tmp = u.val;
            tmp.cost += cost;
            tmp.w += w[v];
            tmp.num++;
            if (tmp.cost == dis[v].cost)
                f[v] += f[u.to];
            else if (tmp.cost < dis[v].cost)
                f[v] = f[u.to];
            if (tmp < dis[v]) {
                dis[v] = tmp;
                pre[v] = u.to;
                pq.push(node(v, tmp));
            }
        }
    }
    int ed = getID("ROM");
    //	cout << ed << endl;
    //	return;
    cout << f[ed] << " " << dis[ed].cost << " " << dis[ed].w << " " << dis[ed].w / (dis[ed].num - 1) << "\n";
    vector<int> res;
    while (ed != -1) {
        res.push_back(ed);
        ed = pre[ed];
    }
    reverse(res.begin(), res.end());
    for (int i = 0; i < SZ(res); ++i) {
        cout << fmp[res[i]];
        if (i != SZ(res) - 1)
            cout << "->";
        else
            cout << "\n";
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    ed = "ROM";
    cin >> n >> m >> st;
    G.clear();
    G.resize(n + 1);
    for (int i = 1, _w; i < n; ++i) {
        string s;
        cin >> s >> _w;
        w[getID(s)] = _w;
    }
    for (int i = 1, u, v, cost; i <= m; ++i) {
        string _u, _v;
        cin >> _u >> _v >> cost;
        u = getID(_u);
        v = getID(_v);
        G[u].push_back(pII(v, cost));
        G[v].push_back(pII(u, cost));
    }
    getID(st);
    //	for (int i = 1; i <= n; ++i) cout << fmp[i] << endl;
    gao(getID(st));
    return 0;
}

Last update: May 4, 2022
Back to top