题目原文及输入/输出格式
题目描述
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; }
   |