• 【DP+拓扑】关键子工程


       【Description】

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

      

    序号 完成时间 子工程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 0  

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

       【Input】

      第1行为N,N是子工程的总个数,N≤200 第2行为N个正整数,分别代表子工程1、2、…、N的完成时间。
      第3行到N+2行,每行有N-1个0或1。
      其中的第I+2行的这些0,1,分别表示“子工程 I”与子工程1、2、…、I-1、I+1、…、N的依赖关系,(I=1,2,…,N)。每行数据之间 均用空格分开。

       【Output】

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

       【Sample Input 1】

    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 Input 2】
    5 5 4 12 7 2 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 1 1 1

       【Sample Output 1】

    14 
    1 3 4 5
    Sample Output 2】
    -1


    【Analysis】
      拓扑排序+DP
      关键子过程即最晚完成时间与最早完成时间相同的子过程。
      第一次使用stack,和priority_queue相似,但stack为先进后出,queue为先进先出,同有top(),pop(),push(),empty(),size()等关键字。
    【Code】
     1 #include<cstdio>
     2 #include<queue>
     3 #include<stack>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 
     8 const int sm = 200+10;
     9 
    10 int n,tot,cnt,maxn,x,d;
    11 int f[sm],g[sm],t[sm],h[sm],rd[sm],hh[sm],cd[sm];
    12 stack<int>s;
    13 
    14 struct edge{
    15     int to,nxt;
    16 }e[sm*2],ee[sm*2];
    17 
    18 void add(int f,int t) {
    19     e[++tot].to=t; e[tot].nxt=h[f]; h[f]=tot; rd[t]++;
    20     ee[tot].to=f; ee[tot].nxt=hh[t]; hh[t]=tot; cd[f]++;
    21 }
    22 
    23 int main() {
    24     
    25     scanf("%d",&n);
    26     for(int i=1;i<=n;++i)scanf("%d",&t[i]);
    27     for(int i=1;i<=n;++i)
    28         for(int j=1;j<=n;++j) {
    29             if(i==j)continue;
    30             scanf("%d",&x);
    31             if(x)add(j,i);
    32         }  
    33         
    34     for(int i=1;i<=n;++i)
    35         if(!rd[i]) s.push(i),f[i]=t[i];
    36         
    37     while(!s.empty()) {
    38         int now=s.top();s.pop();
    39         ++cnt;
    40         for(int i=h[now];i;i=e[i].nxt) {
    41             f[e[i].to]=max(f[e[i].to],f[now]+t[e[i].to]);
    42             rd[e[i].to]--;
    43             if(!rd[e[i].to])s.push(e[i].to);
    44         }
    45     }
    46 
    47     if(cnt!=n){printf("-1
    ");return 0;}
    48     
    49     memset(g,0x3f,sizeof(g));
    50     for(int i=1;i<=n;++i)
    51         if(cd[i]==0) {
    52             s.push(i);
    53             g[i]=maxn;
    54         }
    55     while(!s.empty()) {
    56         int now=s.top();
    57         s.pop();
    58         for(int i=hh[now];i;i=ee[i].nxt) {
    59             g[ee[i].to]=min(g[ee[i].to],g[now]-t[now]);
    60             --cd[ee[i].to];
    61             if(!cd[ee[i].to])s.push(ee[i].to);
    62         }
    63     }
    64     
    65     for(int i=1;i<=n;++i)maxn=max(maxn,f[i]);
    66     printf("%d
    ",maxn);
    67     for(int i=1;i<=n;++i)if(f[i]==g[i])printf("%d ",i);
    68     printf("
    ");
    69     return 0;
    70 }
    
    
    
     
  • 相关阅读:
    linux下安装tomcat
    linux 中安装mysql8.0
    国家助学贷款
    语句摘录
    Java 今天是否为节假日
    Jfinal框架登陆页面的图形验证码
    ActiveRecord初始化,可以实现jfinal系统启动完成后,再建立数据库连接
    socket 通讯
    datatable的excel导入,其中有关于datatables的很多参数设置
    jfinal form表单提交文件
  • 原文地址:https://www.cnblogs.com/Etta/p/6817280.html
Copyright © 2020-2023  润新知