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 }

 

posted @ 2022-05-15 21:40  爱吃虾滑  阅读(27)  评论(0编辑  收藏  举报