P1113 杂务
题目链接 https://www.luogu.com.cn/problem/P1113
拓扑排序模板题+dp
通过读题可以发现这是一道拓扑排序的题目,而我们要输出的答案是【完成所有杂务所需的最短时间】,意思也就是找到所有拓扑序列中总值最小的序列。
(或许可以理解为拓扑序列中的最短路?)
四个主要步骤:
1、初始化队列,将入度为 0 的节点放入队列,并将 dp[i] 的值置为第 i 个杂物所需的时间 tim[i]
2、取出队首,遍历其出边,将能够到达的点入度减一,维护 dp 数组
3、若在此时一个点的入度变为 0,那么将其加入队列
4、回到第二步,直到队列为空
dp[i] 表示第 i 个杂物的最早完成时间
状态转移方程为:dp[next]=max(dp[next],dp[i]+tim[next]),now 为队列顶端的点,next 为 now 能到达的点
在此题中,我们可以用 vector 存下每个杂物的先决杂物
那么最后的答案即为 dp[i] 中的最大值
放AC代码
1 #include<bits/stdc++.h> 2 #define maxn 10010 3 using namespace std; 4 int n,t,e,ans; 5 int tim[maxn],in[maxn],dp[maxn]; 6 vector<int>to[maxn]; 7 queue<int>q; 8 9 int main() 10 { 11 cin>>n; 12 for(int i=1; i<=n; i++) 13 { 14 cin>>t; 15 cin>>tim[t]; 16 cin>>e; 17 while(e!=0) 18 { 19 to[e].push_back(t); 20 in[t]++; 21 cin>>e; 22 } 23 } 24 for(int i=1; i<=n; i++) 25 { 26 if(!in[i]) 27 { 28 q.push(i); 29 dp[i]=tim[i]; 30 } 31 } 32 while(!q.empty()) 33 { 34 int now=q.front(); 35 q.pop(); 36 for(unsigned int i=0; i<to[now].size(); i++) 37 { 38 int next=to[now][i]; 39 dp[next]=max(dp[next],dp[now]+tim[next]); 40 in[next]--; 41 if(in[next]==0) q.push(next); 42 } 43 } 44 for(int i=1; i<=n; i++) 45 ans=max(ans,dp[i]); 46 cout<<ans<<endl; 47 return 0; 48 }