题目原文及输入/输出格式
题目描述
John
的农场在给奶牛挤奶前有很多杂务要完成,每一项杂务都需要一定的时间来完成它。比如:他们要将奶牛集合起来,将他们赶进牛棚,为奶牛清洗乳房以及一些其它工作。尽早将所有杂务完成是必要的,因为这样才有更多时间挤出更多的牛奶。当然,有些杂务必须在另一些杂务完成的情况下才能进行。比如:只有将奶牛赶进牛棚才能开始为它清洗乳房,还有在未给奶牛清洗乳房之前不能挤奶。我们把这些工作称为完成本项工作的准备工作。至少有一项杂务不要求有准备工作,这个可以最早着手完成的工作,标记为杂务 1。John
有需要完成的 n 个杂务的清单,并且这份清单是有一定顺序的,杂务 k(k>1) 的准备工作只可能在杂务 1 至 k-1 中。
写一个程序从 1 到 n 读入每个杂务的工作说明。计算出所有杂务都被完成的最短时间。当然互相没有关系的杂务可以同时工作,并且,你可以假定John
的农场有足够多的工人来同时完成任意多项任务。
解法
本题可以说是拓扑排序的模板题了。
因为计算每一个任务都需要把它的前置任务都计算一遍,所以很容易就想到拓扑排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| #include<cstdio> #include<cmath> #include<cstring> #include<iostream> #include<vector> #include<stack> #include<algorithm> #include<map> #include<queue> #include<stack> #include<climits> using namespace std;
struct edge{ int from, to; edge(int f, int t){ this->from=f; this->to=t; } };
vector<edge> G[10010]; int n, A[10010], ans[10010], in[10010]; queue<int> Q;
int main(){ cin>>n; for(int i=1;i<=n;i++){ int a, b, temp; cin>>a>>b; A[i]=b; cin>>temp; while(temp!=0){ G[temp].push_back(edge(temp, a)); in[i]++; cin>>temp; } } for(int i=1;i<=n;i++) if(in[i]==0){ ans[i]=A[i]; Q.push(i); } while(!Q.empty()){ int node=Q.front(); for(int i=0;i<G[node].size();i++){ edge e=G[node][i]; in[e.to]--; if(in[e.to]==0) Q.push(e.to); ans[e.to]=max(ans[e.to], ans[node]+A[e.to]); } Q.pop(); } int aaa=0; for(int i=1;i<=n;i++){ aaa=max(aaa, ans[i]); } cout<<aaa; return 0; }
|