【DP+拓扑】关键子工程

【Description】

  在大型过程的施工前,我们经常把整个工程分为若干个子工程,并把这些子工程编号为 1、2、…、N;这样划分之后,子工程之间就会有一些依赖关系,即一些子工程必须在 某些子工程完成之后才能施工。由于子工程之间有相互依赖关系,因此有两个任务需要 我们去完成:首先,我们需要根据每个子工程的完成时间计算整个工程最少的完成时间;

  另一方面,由于一些不可预测的客观因素会使某些子工程延期,因此我们必须知道哪些
子工程的延期会影响整个工程的延期,我们把有这种特性的子工程称为关键子工程;因
此第二个任务就是找出所有的关键子工程,以便集中精力管理好这些子工程,尽量避免
这些子工程延期,达到用最快的速度完成整个工程。为了便于编程,现在我们假设: 2根据预算,每一个子工程都有一个完成时间。子工程之间的依赖关系是:部分子工程必须在一些子工程完成之后才开工。 只要满足子工程间的依赖关系,在任何时刻可以有任何多个子工程同时在施工,
也既同时施工的子工程个数不受限制。

  整个工程的完成是指:所有子工程的完成。

  例如,有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\n");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\n",maxn);
67     for(int i=1;i<=n;++i)if(f[i]==g[i])printf("%d ",i);
68     printf("\n");
69     return 0;
70 }

 
时间: 2024-11-01 16:03:52

【DP+拓扑】关键子工程的相关文章

关键子工程

在大型工程的施工前,我们把整个工程划分为若干个子工程,并把这些子工程编号为1.2.…….N:这样划分之后,子工程之间就会有一些依赖关系,即一些子工程必须在某些子工程完成之后才能施工.由于子工程之间有相互依赖关系,因此有两个任务需要我们去完成:首先,我们需要计算整个工程最少的完成时间:同时,由于一些不可预测的客观因素会使某些子工程延期,因此我们必须知道哪些子工程的延期会影响整个工程的延期,我们把有这种特征的子工程称为关键子工程,因此第二个任务就是找出所有的关键子工程,以便集中精力管理好这些子工程,

跟着百度学PHP[4]OOP面对对象编程-7-OOP的一些关键子讲解

面对对象常用的一些关键子:http://www.cnblogs.com/xishaonian/p/6146794.html排版不是很好望见谅. THE END 跟着百度学PHP[4]OOP面对对象编程-7-OOP的一些关键子讲解

ZJU 1346 Comparing Your Heroes 状态压缩DP 拓扑排序的计数

做多校的时候遇见一个求拓扑排序数量的题,就顺便来写了一下. 题意: 你有个朋友是KOF的狂热粉丝,他有一个对其中英雄的强弱比较,让你根据这些比较关系来给这些英雄排名.问一共有多少种排名方式. 思路: 用dp[S]记录当前状态的数量. S表示拓扑排序中当前阶段已经被排序的点的集合.然后就可以枚举当前排序的点,转移的条件是这个点的所有前驱都被排序,而且这个点没被排序.然后转移就好了,最终状态就是所有点都完成排序. 代码: 1 #include <iostream> 2 #include <c

Maven聚合工程安装时排除掉不参与本次安装的子工程

为解决本人在练习项目时的实际需求而做此记录: 在练习SSM项目时,通过Maven的聚合工程搭建了几个module,通过 health_parent 父工程进行管理,内有 healthmobile_web 客户移动端系统, health_web 后台管理系统, springsecuritydemo spring安全框架demo等子工程. 存在问题: 在完成后台管理系统的功能编写后,测试时如果仅需要启动后台系统项目及dubbo服务 health_service ,而通过父工程进行 clean ins

【BZOJ1179】【Apio2009】Atm 强连通分量缩点+拓扑DP/拓扑最长路 kosaraju+tarjan+dfs转非递归三种代码

题解: 首先第一个阶段, 可以写kosaraju.也可以写tarjan. 这两种还都分递归和dfs转非递归. ----------------------------------四种方案. 第二个阶段,可以写拓扑DP 也可以写最长路 ----------------------------------乘上之前的,,八种方案. 本文写了kosaraju递归版,tarjan递归版,kosaraju非递归版. --只怪学校oj系统栈太小..都是逼得啊. 代码1(tarjan): #include <c

Codeforces Round #460 (Div. 2)_D. Substring_[dp][拓扑排序]

题意:一个有向图,每个结点 被赋予一个小写字母,一条路径的value等与这条路径上出现次数最多的字母的数目,求该图的最大value 比赛时,用dfs超时,看官方题解用的dp和拓扑排序,a--z用0-25表示,用dp[i][j]表示以第i个结点结尾的路径上第j个字母出现的次数 拓扑排序每排到一个点,就用该点的dp去更新与它相邻点的dp,最开始入度为0的点特殊处理了一下,dp过程中同步更新结果res 也复习了一下拓扑排序 #include<iostream> #include<cstdio&

[DTOJ3996]:Lesson5!(DP+拓扑+线段树)

题目描述 “最短的捷径就是绕远路,绕远路就是我最短的捷径” 转眼就$Stage\ X$了,$Stage\ X$的比赛路线可以看做一个$n$个点$m$条边的有向无环图,每条边长度都是$1$.杰洛$\cdot$齐贝林会选择走最长的那一条路径. 迪亚哥$\cdot$布兰度决定摧毁一个城市以及所有关于该城市的边,由于变成恐龙后脑子有点问题,他想要让摧毁后的$Stage$最长路径最短,他想知道要摧毁哪个城市,及摧毁后最长路径的长度,如果有多个城市答案相同,则输出编号最小的那一个. 输入格式 本题包含多组数

Codeforces 721C [dp][拓扑排序]

/* 题意:给你一个有向无环图.给一个限定t. 问从1点到n点,在不超过t的情况下,最多可以拜访几个点. 保证至少有一条路时限不超过t. 思路: 1.由无后向性我们可以知道(取决于该图是一个DAG),这题一定可以dp. 2.dp[i][j]代表,到达点i,并且拜访了j个城市的最短时间. wa点: 没有初始化数组中的0.. */ #include<bits/stdc++.h> #define N 5050 using namespace std; int inf=0x3f3f3f3f; int

idea创建父工程子工程与子模块

?首先,我们创建一个新的工作空间 点击File ->New-Project-,弹出以下界面 ?点击Next ?点击Finish,进入到一个新的工作空间 ?创建queen-parent工程 点击File ->New->Module-,进入以下界面 ?点击Next,填写组织名称和项目名称,以及版本号(GAV) ?点击Next ?点击Next,父工程最后一步,给Module取名及选择工作目录 ?点击Finish,完成,如图: ?Pom文件完整如下: <project xmlns=&quo