关键子工程

来源:互联网 发布:mac ftp下载工具 编辑:程序博客网 时间:2024/05/16 04:13

问题描述 Description

在大型工程的施工前,我们把整个工程划分为若干个子工程,并把这些子工程编号为 12N;这样划分之后,子工程之间就会有一些依赖关系,即一些子工程必须在某些子工程完成之后才能施工。由于子工程之间有相互依赖关系,因此有两个任务需要我们去完成:首先,我们需要计算整个工程最少的完成时间;同时,由于一些不可预测的客观因素会使某些子工程延期,因此我们必须知道哪些子工程的延期会影响整个工程的延期,我们把有这种特征的子工程称为关键子工程,因此第二个任务就是找出所有的关键子工程,以便集中精力管理好这些子工程,尽量避免这些子工程延期,达到用最快的速度完成整个工程。为了便于编程,现在我们假设:
( 1 )根据预算,每一个子工程都有一个完成时间。
( 2 )子工程之间的依赖关系是:部分子工程必须在一些子工程完成之后才开工。
( 3 )只要满足子工程间的依赖关系,在任何时刻可以有任何多个子工程同时在施工,也既同时施工的子工程个数不受限制。
( 4 )整个工程的完成是指:所有子工程的完成。

例如,有五个子工程的工程规划表:

序号 完成时间 子工程1 子工程2 子工程3 子工程4 子工程5 子工程 1 5 0 0 0 0 子工程 2 4 0 0 0 0 子工程 3 12 0 0 0 0 子工程 4 7 1 1 0 0 子工程 5 2 1 1 1 1

其中,表格中第 I+1J+2 列的值如为 0 表示“子工程 I ”可以在“子工程 J ”没完成前施工,为 1 表示“子工程 I ”必须在“子工程 J ”完成后才能施工。上述工程最快完成时
间为 14 天,其中子工程 1345 为关键子工程。

又例如,有五个子工程的工程规划表:

序号 完成时间 子工程1 子工程2 子工程3 子工程4 子工程5 子工程 1 5 0 1 0 0 子工程 2 4 0 0 0 0 子工程 3 12 0 0 1 0 子工程 4 7 1 1 0 0 子工程 5 2 1 1 1 1

上述的子工程划分不合理,因为无法安排子工程 134 的施工。


输入描述 Input Description

1 行为 NN 是子工程的总个数, N200
2 行为 N 个正整数,分别代表子工程 12N 的完成时间。
3 行到 N+2 行,每行有 N101 。其中的第 I+2 行的这些 01,分别表示“子工程 I ”与子工程 12I1I+1N 的依赖关系,( I=12N )。每行数据之间均用一个空格分开。


输出描述 Output Description

如子工程划分不合理,则输出 1
如子工程划分合理,则用两行输出:第 1 行为整个工程最少的完成时间。第 2 行为按由
小到大顺序输出所有关键子工程的编号。


输入样例 Sample Input

5
5 4 12 7 2
0 0 0 0
0 0 0 0
0 0 0 0
1 1 0 0
1 1 1 1


输出样例 Sample Output

14
1 3 4 5


分析 I Think

对于整个工程,可以看作一个有向图,如果能进行拓扑排序,那么他就有解。如果一个点的最迟发生时间等于它的最早发生时间,那么他就是一个关键子工程,注意可能有多个点出度为 0


代码 Code

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int last[201];int early[201];int du[201][2];int order[201];int a[201][201];int time[201];int stack[201],top=-1;int n;bool tp_sort();int main(){    scanf("%d",&n);    for(int i=1;i<=n;++i)        scanf("%d",&time[i]);    for(int i=1;i<=n;++i){        for(int j=1;j<i;++j){            scanf("%d",&a[i][j]);            if(a[i][j]){                ++du[i][0];                ++du[j][1];            }        }        for(int j=i+1;j<=n;++j){            scanf("%d",&a[i][j]);            if(a[i][j]){                ++du[i][0];                ++du[j][1];            }        }    }    if(!tp_sort()){        puts("-1");        return 0;    }    for(int i=1;i<=n;++i)        for(int j=1;j<=n;++j)            if(a[j][order[i]])                early[j] = max(early[j],early[order[i]]+time[order[i]]);    int maxn = -1;    memset(last,0x7f,sizeof last);    for(int i=1;i<=n;++i)        if(!du[i][1])            maxn = max(maxn,early[i]+time[i]);    for(int i=1;i<=n;++i)        if(!du[i][1])            last[i] = maxn-time[i];    for(int i=n;i>=1;--i)        for(int j=1;j<=n;++j)            if(a[order[i]][j])                last[j] = min(last[j],last[order[i]]-time[j]);    printf("%d\n",maxn);    for(int i=1;i<=n;++i)        if(last[i] == early[i])            printf("%d ",i);    return 0;}bool tp_sort(){    top = -1;    for(int i=1;i<=n;++i)        if(!du[i][0])            stack[++top] = order[++order[0]] = i;    while(top != -1){        int now = stack[top--];        for(int i=1;i<=n;++i){            if(a[i][now]){                --du[i][0];                if(!du[i][0])                    stack[++top] = order[++order[0]] = i;            }        }    }    return order[0] == n;}   
0 0