P1113 杂务(拓扑排序)

题意:

有n个任务,每个任务完成都有其所需的时间,并且有其前置任务,问完成所有任务要多久(没有直接关系的任务可以同时开始)

思路:

自己写的稍稍有些复杂

首先建图,对于一个任务给所有其前置任务连一条有向边(从前置连向自己),并记录一个点的入读

之前遍历一遍,将入度为0的点加入队列中,边将其所有相邻的点入度减一,如果有入度为0的点,则加入队列中

比较关键的一点就是如何更新时间dp[nex]=max(dp[nex],dp[i]+tim[nex])

我的写法较为复杂,还多用了一个队列存时间,用一个DP数组就能直接解决了

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#define inf 0x3f3f3f3f
 using namespace std;
 const int maxn=1e5+10;
 queue<int> a,b;
 vector<int> edge[maxn];
 int in[maxn],tim[maxn],ans,n,mx[maxn];
 void solve()
 {
     for(int i=1;i<=n;i++){
         if(!in[i]){
             a.push(i),b.push(tim[i]);
         }
     }
     while(!a.empty()){
         int x=a.front(),y=b.front();
         a.pop(),b.pop();
         ans=max(ans,y);
         for(int i=0;i<edge[x].size();i++){
             in[edge[x][i]]--;
             mx[edge[x][i]]=max(y,mx[edge[x][i]]);
             if(!in[edge[x][i]]){
                 a.push(edge[x][i]);
                 b.push(tim[edge[x][i]]+mx[edge[x][i]]);
             }
         }
     }
 }
 int main()
 {
     int x,y,temp;
     scanf("%d",&n);
     for(int i=1;i<=n;i++){
         scanf("%d%d",&x,&y);
         tim[x]=y;
         while(scanf("%d",&temp)&&temp){
             edge[temp].push_back(x);
             in[x]++;
         }
     }
     memset(mx,-inf,sizeof(mx));
     ans=-inf;
     solve();
     cout<<ans<<endl;
 }

猜你喜欢

转载自www.cnblogs.com/overrate-wsj/p/12309442.html
今日推荐