Luogu P1113 杂务 【拓扑排序】 By cellur925

题目传送门

这题我们一看就知道是拓扑排序,然而在如何转化问题上花了大工夫,一个小时后最后还是无奈看了题解qwq。

显然我们可以对于每个任务,从他的前导任务到他连一条边,最后我们可以得到一个DAG。在这个DAG上进行拓扑排序,更新做到第j号任务的花费,花费就是max(f[j],f[i]+val[j])。当我们找到一个出度为0的点,就可以用它更新最终答案。

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<queue>
 4 
 5 using namespace std;
 6 
 7 int n,ans,tot,cnt;
 8 int val[10090],du[10090],head[10090],f[10090],cdu[10090];
 9 struct node{
10     int next,to;
11 }edge[200900];
12 
13 void add(int x,int y)
14 {
15     edge[++tot].next=head[x];
16     head[x]=tot;
17     edge[tot].to=y;
18 }
19 
20 void topo()
21 {
22     queue<int>q;
23     for(int i=1;i<=n;i++)
24         if(du[i]==0) q.push(i),f[i]=val[i];
25     while(!q.empty())
26     {
27         int x=q.front();q.pop();
28         for(int i=head[x];i;i=edge[i].next)
29         {
30             int y=edge[i].to;
31             f[y]=max(f[y],f[x]+val[y]);
32             if(--du[y]==0)
33             {
34                 if(!cdu[y]) ans=max(ans,f[y]);
35                 else q.push(y);
36             }
37         }
38     }
39 }
40 
41 int main()
42 {
43     scanf("%d",&n);
44     for(int i=1;i<=n;i++)
45     {
46         int opt=0,y=0;
47         scanf("%d%d",&opt,&val[i]);
48         while(scanf("%d",&y)&&y!=0) add(opt,y),du[y]++,cdu[opt]++;
49     }
50     topo();
51     printf("%d",ans);
52     return 0;
53 }
View Code

细节:本题开数组大小比较讲究,邻接表的大小不好掌控,开始就RE了一个点。

*Update8.29 : 在本题中,虽然要求最小时间,但也要求完成全部任务。

       最小我们使用的是拓扑序来维护的,而完成全部任务则是在更新答案时去max来维护的。

 

另:Chemist说他读入的时候会32212225477,原因是读入不定数据没有赋初值(看来我的开始赋0是个好习惯orz)

posted @ 2018-08-14 23:08  cellur925&Chemist  阅读(139)  评论(0编辑  收藏  举报