7-4 Professional Ability Test (30 分)

#include <algorithm>
#include <iostream>
#include <queue>
#include <unordered_set>
#include <vector>

using namespace std;

struct Node {
    int T, S;
    Node() {}
    Node(int T, int S) : T(T), S(S) {}
};

bool is_consistent(vector<vector<Node>> &adj, unordered_set<int> &entrances) {
    vector<int> indegree(adj.size());
    for (int i = 0; i < adj.size(); i++) {
        for (int j = 0; j < adj[i].size(); j++) {
            indegree[adj[i][j].T]++;
        }
    }

    queue<int> q;
    for (int i = 0; i < indegree.size(); i++) {
        if (indegree[i] == 0) {
            q.push(i);
            entrances.insert(i);
        }
    }

    while (!q.empty()) {
        int f = q.front();
        q.pop();
        for (int i = 0; i < adj[f].size(); i++) {
            indegree[adj[f][i].T]--;
            if (indegree[adj[f][i].T] == 0) {
                q.push(adj[f][i].T);
            }
        }
    }

    for (int i = 0; i < indegree.size(); i++) {
        if (indegree[i] != 0)
            return false;
    }
    return true;
}

void dijkstra(int start, vector<vector<Node>> &adj, vector<vector<int>> &pre) {
    vector<int> visited(adj.size(), false), score(adj.size(), -1);

    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    pq.push({0, start});
    score[start] = 0;

    while (!pq.empty()) {
        auto top = pq.top();
        pq.pop();

        int s = top.first, u = top.second;

        visited[u] = true;

        if (score[u] != -1 && score[u] < s)
            continue;

        for (int i = 0; i < adj[u].size(); i++) {
            auto &v = adj[u][i];
            if (!visited[v.T] and (score[v.T] == -1 or score[v.T] >= score[u] + v.S)) {
                if (score[v.T] == -1 || score[v.T] > score[u] + v.S) {
                    score[v.T] = score[u] + v.S;
                    pq.push({score[v.T], v.T});
                    pre[v.T].clear();
                }
                pre[v.T].push_back(u);
            }
        }
    }
}

void dfs(int end, vector<vector<int>> &pre, vector<int> &tmp_path, vector<int> &path,
         vector<vector<int>> &vouchers, int &max_voucher, int cur_voucher) {
    if (pre[end].empty()) {
        if (cur_voucher > max_voucher) {
            path = tmp_path;
            path.pop_back();
            max_voucher = cur_voucher;
        }
        return;
    }
    for (auto i : pre[end]) {
        tmp_path.push_back(i);
        dfs(i, pre, tmp_path, path, vouchers, max_voucher, cur_voucher + vouchers[end][i]);
        tmp_path.pop_back();
    }
}

int main() {
    int N, M;
    cin >> N >> M;

    vector<vector<Node>> adj(N + 1);
    vector<vector<int>> vouchers(N + 1, vector<int>(N + 1));

    int T1, T2, S, D;
    for (int i = 0; i < M; i++) {
        cin >> T1 >> T2 >> S >> D;
        adj[T1].emplace_back(T2, S);
        vouchers[T1][T2] = vouchers[T2][T1] = D;
    }

    // 判断图中是否有环,并找到所有的入口
    unordered_set<int> entrances;
    bool consistent = is_consistent(adj, entrances);
    if (consistent) {
        cout << "Okay.\n";
    } else {
        cout << "Impossible.\n";
    }

    // 用一个超级节点连接所有的入口,使之成为唯一的入口
    for (auto entrance : entrances) {
        adj[N].emplace_back(entrance, 0);
    }

    vector<vector<int>> pre(N + 1);
    if (consistent)
        dijkstra(N, adj, pre);

    int K;
    cin >> K;

    int x;
    for (int i = 0; i < K; i++) {
        cin >> x;
        if (entrances.count(x)) {
            cout << "You may take test " << x << " directly.\n";
        } else if (consistent) {
            int max_voucher = 0;
            vector<int> path, tmp_path = {x};
            dfs(x, pre, tmp_path, path, vouchers, max_voucher, 0);

            for (auto i = path.rbegin(); i != path.rend(); i++) {
                cout << *i;
                if (i + 1 != path.rend()) {
                    cout << "->";
                } else {
                    cout << "\n";
                }
            }
        } else {
            cout << "Error.\n";
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值