这题我们一看就知道是拓扑排序,然而在如何转化问题上花了大工夫,一个小时后最后还是无奈看了题解qwq。
显然我们可以对于每个任务,从他的前导任务到他连一条边,最后我们可以得到一个DAG。在这个DAG上进行拓扑排序,更新做到第j号任务的花费,花费就是max(f[j],f[i]+val[j])。当我们找到一个出度为0的点,就可以用它更新最终答案。
code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
细节:本题开数组大小比较讲究,邻接表的大小不好掌控,开始就RE了一个点。
*Update8.29 : 在本题中,虽然要求最小时间,但也要求完成全部任务。
最小我们使用的是拓扑序来维护的,而完成全部任务则是在更新答案时去max来维护的。
另:Chemist说他读入的时候会32212225477,原因是读入不定数据没有赋初值(看来我的开始赋0是个好习惯orz)