题意:
有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; }
来源:https://www.cnblogs.com/overrate-wsj/p/12309442.html