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
N?1) 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:
#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;
}
|