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;
}

如果你不开心,那我就把右边这个帅傻子分享给你吧,   

你看,他这么好看,那么深情的望着你,你还伤心吗?   

真的!这照片盯上他五秒钟就想笑了。   

一切都会过去的。 

posted @ 2018-10-28 20:20  孟东行#  阅读(324)  评论(2编辑  收藏  举报