PAT(甲级)2020年秋季考试 7-4 Professional Ability Test (C++)

Professional Ability Test (PAT) consists of several series of subject tests. Each test is divided into several levels. Level A is a prerequisite (前置要求) of Level B if one must pass Level A with a score no less than S S S in order to be qualified to take Level B. At the mean time, one who passes Level A with a score no less than S S S will receive a voucher(代金券)of D D D yuans (Chinese dollar) for taking Level B.

At the moment, this PAT is only in design and hence people would make up different plans. A plan is NOT consistent if there exists some test T so that T is a prerequisite of itself. Your job is to test each plan and tell if it is a consistent one, and at the mean time, find the easiest way (with minimum total S S S) to obtain the certificate of any subject test. If the easiest way is not unique, find the one that one can win the maximum total value of vouchers.

Input Specification:

Each input file contains one test case. For each case, the first line gives two positive integers N ( ≤ 1000 ) N (≤1000) N(1000) and M M M, being the total numbers of tests and prerequisite relations, respectively. Then M M M lines follow, each describes a prerequisite relation in the following format:

T1 T2 S D

where T1 and T2 are the indices (from 0 to N − 1 N−1 N1) of the two distinct tests; S is the minimum score (in the range (0, 100]) required to pass T1 in order to be qualified to take T2; and D is the value of the voucher (in the range (0, 500]) one can receive if one passes T1 with a score no less than S and plan to take T2. It is guaranteed that at most one pair of S and D are defined for a prerequisite relation.

Then another positive integer K ( ≤ N ) K (≤N) K(N) is given, followed by K K K queries of tests. All the numbers in a line are separated by spaces.

Output Specification:

Print in the first line Okay. if the whole plan is consistent, or Impossible. if not.
If the plan is consistent, for each query of test T, print in a line the easiest way to obtain the certificate of this test, in the format:

T0->T1->...->T

However, if T is the first level of some subject test (with no prerequisite), print You may take test T directly. instead.

If the plan is impossible, for each query of test T, check if one can take it directly or not. If the answer is yes, print in a line You may take test T directly.; or print Error. instead.

Sample Input 1:

8 15
0 1 50 50
1 2 20 20
3 4 90 90
3 7 90 80
4 5 20 20
7 5 10 10
5 6 10 10
0 4 80 60
3 1 50 45
1 4 30 20
1 5 50 20
2 4 10 10
7 2 10 30
2 5 30 20
2 6 40 60
8
0 1 2 3 4 5 6 7

Sample Output 1:

Okay.
You may take test 0 directly.
0->1
0->1->2
You may take test 3 directly.
0->1->2->4
0->1->2->4->5
0->1->2->6
3->7

Sample Input 2:

4 5
0 1 1 10
1 2 2 10
3 0 4 10
3 2 5 10
2 0 3 10
2
3 1

Sample Output 2:

Impossible.
You may take test 3 directly.
Error.

Caution:

考试的时候第一题盆盆奶那个浪费了点时间,再加上这道题刚开始没有看出来是要检查 DAG,并且 Dijkstra 确实不是很熟悉,所以一开始用的 DFS ,果然超时,但后来也没时间改了,结束后查了一下这道题的解答,这篇解释得挺详细的,下面的代码是看了这篇的思路后写出来的。

(注:由于没有提交的机会了,所以下面的代码不保证 AC,但上面那篇文章里面有 AC 代码)

Solution:

// Talk is cheap, show me the code
// Created by Misdirection 2021-09-08 14:59:41
// All rights reserved.

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

int n, m;
vector<vector<int>> prerequisite;
int sMap[1010][1010], dMap[1010][1010];
int inDegree[1010], inDegree2[1010];

bool vis[1010];
int dis[1010];
int yuans[1010];
int pre[1010];

bool judgeDAG(){
    queue<int> q;
    int cnt = 0;

    for(int i = 0; i < n; ++i){
        if(inDegree2[i] == 0) q.push(i);
    }

    while(!q.empty()){
        cnt++;

        int tmp = q.front();
        q.pop();

        for(int j = 0; j < prerequisite[tmp].size(); ++j){
            inDegree2[prerequisite[tmp][j]]--;
            if(inDegree2[prerequisite[tmp][j]] == 0) q.push(prerequisite[tmp][j]);
        }
    }

    return cnt == n;
}

void dijkstra(){

	fill(vis, vis + 1010, false);
    fill(dis, dis + 1010, 2147483647);
    fill(yuans, yuans + 1010, 0);
    
    dis[n] = 0;
    for(int i = 0; i <= n; ++i){
        int u = -1, minLen = 2147483647;

        for(int j = 0; j <= n; ++j){
            if(!vis[j] && dis[j] < minLen){
                u = j;
                minLen = dis[j];
            }
        }

        if(u == -1) return;
        vis[u] = true;

        for(int x = 0; x < prerequisite[u].size(); ++x){
            int v = prerequisite[u][x];

            if(!vis[v]){
                if(dis[v] > dis[u] + sMap[u][v]){
                    dis[v] = dis[u] + sMap[u][v];
                    yuans[v] = yuans[u] + dMap[u][v];
                    pre[v] = u;
                }
                else if(dis[v] == dis[u] + sMap[u][v] && yuans[u] + dMap[u][v] > yuans[v]){
                    yuans[v] = yuans[u] + dMap[u][v];
                    pre[v] = u;
                }
            }
        }
    }
}

int main(){
    
    scanf("%d %d", &n, &m); 
    prerequisite.resize(n + 1);

    for(int i = 0; i < m; ++i){
        int t1, t2, s, d;

        scanf("%d %d", &t1, &t2);
        scanf("%d %d", &sMap[t1][t2], &dMap[t1][t2]);
        inDegree[t2]++;
        inDegree2[t2]++;
        prerequisite[t1].push_back(t2);
    }

    int k;
    scanf("%d", &k);

    if(judgeDAG()){
        printf("Okay.\n");

        for(int i = 0; i < n; ++i){
            if(inDegree[i] == 0){
                prerequisite[n].push_back(i);
                sMap[n][i] = dMap[n][i] = 0;
            }
        }

        dijkstra();

        for(int i = 0; i < k; ++i){
            int tmp;
            scanf("%d", &tmp);

            if(inDegree[tmp] == 0){
                printf("You may take test %d directly.\n", tmp);
                continue;
            }

            vector<int> ans;
            int x = tmp;

            while(true){
                if(x == n) break;
                ans.push_back(x);
                x = pre[x];
            }

            for(int j = ans.size() - 1; j >= 0; --j){
                if(j == 0) printf("%d\n", ans[j]);
                else printf("%d->", ans[j]);
            }
        }
    }

    else{
        printf("Impossible.\n");

        for(int i = 0; i < k; ++i){
            int tmp;
            scanf("%d", &tmp);

            if(inDegree[tmp] == 0) printf("You may take test %d directly.\n", tmp);
            else printf("Error.\n");
        }
    }
    
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

负反馈循环

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值