P1113 杂务
此题困扰本宫甚久。(还不是太菜。)
咳咳,再说一下题意啊。。。
有n个任务,要完成每个任务都需要一个相应的时间,
而有的任务在完成之前必须要完成它对应的准备任务。
问完成所有的任务最少需要多少时间?
搜到一份代码emm,长这样,
虽然短小精悍,,但还是没看懂。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; int n,i,t,x,ans; int a[10002]; int main() { scanf("%d",&n); while(n--) { scanf("%d%d",&i,&t); while(scanf("%d",&x)&&x!=0) a[i]=max(a[i],a[x]); a[i]+=t; ans=max(ans,a[i]); } printf("%d",ans); return 0; }
然后,为什么呢?
我们考虑,每个任务要想开始的话,就必须要完成他所有的准备任务,
那么这个任务开始的时间就是他所有的准备任务中最晚结束的时间;
然后这个时间再加上做这个任务本身需要的时间,就是这个任务结束的时间了。
然后任务结束最晚的就是我们要的答案了。
这样看来思路好像很清晰,,,,代码也很明白。。。
那我当时是怎么不明白的。。。晕。
据说skr很明显的拓扑题,每个点只有入度为0的时候才可以入队。
上个图吧,源自whymhe。。
解释一下:
这个点(任务)被访问,必须要在他前面的点(他的所有准备任务)全被访问之后,
然后要在它前面的点的结束时间中取个最大值,就是这个任务的开始时间……
(同上同上)
1的结束时间:5
2的结束时间:1+5=6
4的结束时间:5+6=11
3的结束时间:6+3=8
5的结束时间:11(最大的)+1=12
6的结束时间:11(max)+8=19
7结束的时间:19(3,5,6中的max)+4=23
所以拓扑代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; typedef long long LL; inline int read() { char c=getchar(); int num=0; for(; !isdigit(c); c=getchar()); for(; isdigit(c); c=getchar()) num=num*10+c-'0'; return num; } const int N=1e4+5; const int INF=1<<30; int n; int rudu[N]; int f[N],g[N]; int ans; int head[N],num_edge; struct Edge { int v,nxt; } edge[N*1005]; inline void add_edge(int u,int v) { edge[++num_edge].v=v; edge[num_edge].nxt=head[u]; head[u]=num_edge; } queue<int> que; void topsort() { for(int i=1; i<=n; ++i) if(rudu[i]==0) que.push(i); int now; while(!que.empty()) { now=que.front(),que.pop(); f[now]+=g[now]; if(head[now]==0) ans=max(ans,f[now]); for(int i=head[now],v; i; i=edge[i].nxt) { v=edge[i].v; --rudu[v]; if(rudu[v]==0) que.push(v); g[v]=max(g[v],f[now]); } } } int main() { n=read(); for(int i=1,a,b; i<=n; ++i) { a=read(),f[a]=read(); while(scanf("%d",&b)&&b) { add_edge(b,a); ++rudu[a]; } } topsort(); cout<<ans; return 0; }
如果你不开心,那我就把右边这个帅傻子分享给你吧,
你看,他这么好看,那么深情的望着你,你还伤心吗?
真的!这照片盯上他五秒钟就想笑了。
一切都会过去的。