题目链接
看了好多题解都是用的dijkstra,发一个我这种菜j的纯dfs写法
题目
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 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 will receive a voucher(代金券)of 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) 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) and M, being the total numbers of tests and prerequisite relations, respectively. Then 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) 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) is given, followed by 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.
代码长度限制:16 KB
时间限制:3000 ms
内存限制:64 MB
栈限制:8192 KB
题目大意
- PAT有多考测试的级别,每个级别的测试会有对应的前置测试条件及相应及格线S和奖励D
- 给出测试数量N,测试前置条件M个,M个测试之间的关系T1,T2,S,D,想要参加T2要先完成T1,一个T2可能有不同的前置T1
- 最后给出K个测试,要求判断这些测试中的前置条件是否存在环,若存在输出
Impossible.
,随后对每个测试判断是否有前置条件,没有输出You may take test 该测试 directly.
,有输出Error.
;若不存在环输出Okay.
后,随后对每个测试判断是否有前置条件,有输出整个序列
,无输出You may take test 该测试 directly.
。
思路
- 用vector容器记录每个级别测试的所有前置测试条件及相应及格线S和奖励D
- 用dfs搜索vector容器是否存在环,并用flag标记
- 有环,则直接根据每个测试是否存在前置条件进行对应输出
- 无环,再用dfs搜索vector中所有路径,找到完成每个测试所需的最小总S(或存在相同最小总S时的最大总D)的序列。
注意!
- 1.dfs1函数(判断有无环)判断是否有环时要用vis标记走过的点,避免重复搜索
- 2.dfs2函数深搜结果时当sums>mins时这条路径注定不会是最小S了,所以退出该路径的搜索
- 否则测试点7超时
代码
#include <iostream>
#include <vector>
using namespace std;
int n,m,k,flag = 1,a[1005],t,vis[1005] = {0};
struct Node{
int pre,s,d;
};
vector<Node> g[1005]; // 每个测试的所有前置测试
int mins,maxd;
// 判断是否有环
void dfs1(int v){
if(flag==0) return;
if(vis[v]) return;
vis[v] = 1;
for(int i=0;i<g[v].size();i++){
if(g[v][i].pre==t){
flag = 0;
break;
}
dfs1(g[v][i].pre);
}
}
vector<int> ans,temp;
// 深搜结果
void dfs2(int v,int sums,int sumd){
temp.push_back(v);
if(sums>mins){
temp.pop_back();
return;
}
// 搜索到底
if(g[v].empty()){
if(sums<mins){
ans = temp;
mins = sums;
maxd = sumd;
}
else if(sums==mins&&sumd>maxd){
ans = temp;
maxd = sumd;
}
temp.pop_back();
return;
}
for(int i=0;i<g[v].size();i++){
dfs2(g[v][i].pre,sums+g[v][i].s,sumd+g[v][i].d);
}
temp.pop_back();
}
signed main()
{
cin>>n>>m;
for(int i=0;i<m;i++){
int t1,t2,s,d;
cin>>t1>>t2>>s>>d;
g[t2].push_back({t1,s,d});
}
cin>>k;
// 判断每个待查测试点是否有环
for(int i=0;i<k;i++){
cin>>a[i];
t = a[i];
for(int j=0;j<n;j++) vis[j] = 0;
if(flag)
dfs1(t);
}
// 无环:深搜结果
if(flag){
printf("Okay.\n");
for(int i=0;i<k;i++){
mins = 0x3f3f3f,maxd = 0;
if(g[a[i]].empty()) printf("You may take test %d directly.",a[i]);
else{
dfs2(a[i],0,0);
cout<<ans[ans.size()-1];
for(int i=ans.size()-2;i>=0;i--) cout<<"->"<<ans[i];
}
cout<<"\n";
}
}
// 有环
else{
printf("Impossible.\n");
for(int i=0;i<k;i++){
if(g[a[i]].empty()) printf("You may take test %d directly.\n",a[i]);
else printf("Error.\n");
}
}
return 0;
}