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;
}
如果你不开心,那我就把右边
这个帅傻子分享给你吧,
你看,他这么好看,那么深情的望着你,你还伤心吗?
真的!这照片盯上他五秒钟就想笑了。
一切都会过去的。

浙公网安备 33010602011771号