题目
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]);
}
}