GDKOI2014「壕壕的寒假作业」

本文描述了一种通过两次深度优先搜索解决壕壕作业规划问题的方法。壕壕需要在班主任规定的截止日期前完成所有作业,同时遵循自己设定的作业顺序规则。文章详细介绍了如何通过DFS算法确定每份作业最早和最晚的完成时间,以避免受到惩罚。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

Description
下课了,还沉浸在阶乘世界的壕壕被斑主任交到了办公室。
“壕壕,你的寒假作业呢?还没做吧?你家里人知道吗?”真相被拆穿,惊呆了的壕壕只好向班主任坦白自己玩了一个寒假,作业还没有开始做。班主任决定给壕壕最后一次机会,让他给每一份作业设置一个截止期限,只要壕壕每份作业在对应的期限前完成,就不会受到惩罚。每当壕壕做作业的时候,他的强迫症就会发作。壕壕会对作业定下一些规则,有的作业只能在其他某些作业完成之后才能开始做。比如说:壕壕规定数学作业要在语文作业前完成那么语文作业就不会在数学作业前做。此外,壕壕的规则不会产生环,也就是说,数学作业要在语文作业前完成、语文作业要在英语作业前完成、英语作业要在数学作业前完成这种情况不会出现,否则壕壕就会放弃治疗,从而受到主任的惩罚。由于壕壕精力充沛,所以壕壕不会休息,只会不停地做作业。但同时他也是一个普通人所以他同一时刻不能做两份或以上作业壕壕想对班主任说每份作业最晚能在什么时刻完成,这样无论他怎么安排作业的顺序都不会受到惩罚。但同时,班主任也想知道每份作业最早能在什么时刻完成,从而可以更好地催促壕壕完成作业。班主任想知道自己需要的答案,于是他求助于你一一全班最聪明机智的同学。同时壕壕也想知道自己需要的答案,于是他求助于你一一他的同桌。你能告诉他们吗?

Sample Input

4 4
3 4 5 6
1 2
1 3
2 4
3 4

Sample Output

3 3
7 12
8 12
18 18

思路

如果要最快完成第 i 份作业,那么需要完成 i 的前继那些作业,那么最优方案即为优先处理 i 的前驱。
如果是要最慢完成第 i 份作业,最优方案则为除了它的后继外所有的作业都做。
那么跑两遍 dfs 处理对于每个 i 的前驱 & 后继就可以了。

#include <stdio.h>
#include <string.h>
#define re register
using namespace std;

int fast, slow;
void search1(int x);
void search2(int x);

const int maxn=2005;
int n, m;
int a, b;
int Time[maxn], Sum (0);
int son[maxn][maxn];
int fa[maxn][maxn];
bool flag[maxn];
int main() {
	scanf("%d %d", &n, &m);
	for (re int i=1; i<=n; i++) {
		scanf("%d", &Time[i]);
		Sum+=Time[i];
	}
	for (re int i=1; i<=m; i++) {
		scanf("%d %d", &a, &b);
		son[b][++son[b][0]]=a;
		fa[a][++fa[a][0]]=b;
	}
	
	for (re int i=1; i<=n; i++) {
		fast=0;
		memset(flag, 0, sizeof flag);
		search1(i);
		
		slow=-Time[i];
		memset(flag, 0, sizeof flag);
		search2(i);
		
		printf("%d %d\n", fast, Sum-slow);
	}
	
	return 0;
}

void search1(int x) {
	if (flag[x]) return ;
	
	fast+=Time[x];
	flag[x]=1;
	
	for (re int i=1; i<=son[x][0]; i++) {
		search1(son[x][i]);
	}
}

void search2(int x) {
	if (flag[x]) return ;
	
	slow+=Time[x];
	flag[x]=1;
	
	for (re int i=1; i<=fa[x][0]; i++) {
		search2(fa[x][i]);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值