题目链接:https://www.luogu.org/problemnew/show/P1113
打眼一看,这不就是道拓扑排序的问题?不过和一般的拓扑排序不同,这里不只是要求一个完成工作的次序,每个工作都有相应的完成所需时间,要求完成所有工作所需的最短时间。之所以这里会有最短时间,是因为已完成准备工作的任务可以同时进行,只要每项工作能完则完,那么最终所有工作都完成所需的时间就是最短的(废话)。还是拓扑排序的思路,只需要这样想,设定一个early数组表示每项工作的最早开始时间,他就等于该工作所有准备工作中,完成最晚的。答案就是整个过程中所经历过最晚的完成时间。
1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 inline int get_num() { 8 int num;char c; 9 while((c=getchar())=='\n'||c==' '||c=='\r'); 10 num=c-'0'; 11 while(isdigit(c=getchar())) num=num*10+c-'0'; 12 return num; 13 } 14 const int maxn=1e4+5,maxm=1e6+5; 15 int n,len[maxn],head[maxn],eid,ind[maxn],early[maxn],ans; 16 struct edge { 17 int v,next; 18 } E[maxm]; 19 void insert(int u,int v) { 20 E[eid].v=v; 21 E[eid].next=head[u]; 22 head[u]=eid++; 23 } 24 queue<int> q; 25 int main() { 26 n=get_num(); 27 memset(head,-1,sizeof(head)); 28 int in,new_t; 29 for(int i=1;i<=n;++i) { 30 get_num();len[i]=get_num(); 31 while((in=get_num())) insert(in,i),++ind[i]; //注意是有一条从in到i的边 32 if(!ind[i]) q.push(i); 33 } 34 while(!q.empty()) { //队列中存放当前入度为0的点 35 int u=q.front();q.pop(); 36 new_t=early[u]+len[u]; 37 ans=max(ans,new_t); //统计答案 38 for(int p=head[u];p+1;p=E[p].next) { 39 int v=E[p].v; 40 early[v]=max(early[v],new_t); //更新每项工作的最早开始时间 41 if(!(--ind[v])) q.push(v); 42 } 43 } 44 printf("%d",ans); 45 return 0; 46 }