【题目大意】
在大型工程的施工前,我们把整个工程划分为若干个子工程,并把这些子工程编号为1、2、……、N;这样划分之后,子工程之间就会有一些依赖关系,即一些子工程必须在某些子工程完成之后才能施工。由于子工程之间有相互依赖关系,因此有两个任务需要我们去完成:首先,我们需要计算整个工程最少的完成时间;同时,由于一些不可预测的客观因素会使某些子工程延期,因此我们必须知道哪些子工程的延期会影响整个工程的延期,我们把有这种特征的子工程称为关键子工程,因此第二个任务就是找出所有的关键子工程,以便集中精力管理好这些子工程,尽量避免这些子工程延期,达到用最快的速度完成整个工程。为了便于编程,现在我们假设:
(1)根据预算,每一个子工程都有一个完成时间。
(2)子工程之间的依赖关系是:部分子工程必须在一些子工程完成之后才开工。
(3)只要满足子工程间的依赖关系,在任何时刻可以有任何多个子工程同时在施工,也既同时施工的子工程个数不受限制。
(4)整个工程的完成是指:所有子工程的完成。
例如,有五个子工程的工程规划表:
【输出格式】
如子工程划分不合理,则输出-1;
如子工程划分合理,则用两行输出:第1行为整个工程最少的完成时间。第2行为按由小到大顺序输出所有关键子工程的编号。
【样例】
输入文件名:project.in
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
输出文件名:project.out
14
1 3 4 5
先用拓扑排序判断是否合理,再分别求出一个子工程的最早最晚开工时间,判断是否有时间空隙,如果没有就是不能延期的关键子工程。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200+10;
int n,mi[maxn],ma[maxn],t[maxn],into[maxn],g[maxn][maxn],v[maxn];//mi(i):最早可以开始时间,ma(i):最晚必须开始时间
int ans=0;
void init()
{
freopen("project.in","r",stdin);
freopen("project.out","w",stdout);
}
void readdata()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&t[i]);
memset(into,0,sizeof(into));
memset(g,0,sizeof(g));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) continue;
scanf("%d",&g[j][i]);
if(g[j][i]) into[i]++;
}
}
}
void tuopu() //循环每个子工程,假设这个子工程完成,然后改变相应的into[i]
{
for(int i=1;i<=n;i++)
{
int j=1;
while(j)
{
if(into[j]) j++;
else break;
if(j>n)
{
printf("-1\n");
exit(0);
}
}
into[j]=1000000;
for(int i=1;i<=n;i++)
{
if(g[j][i]) into[i]--;
}
}
}
int dfsmin(int i)
{
if(v[i]) return mi[i];
v[i]=1;
mi[i]=0;
for(int j=1;j<=n;j++)//枚举前趋节点
{
if(g[j][i])
{
mi[i]=max(mi[i],dfsmin(j)+t[j]);
}
}
return mi[i];
}
int dfsmax(int i)
{
if(v[i]) return ma[i];
v[i]=1;
ma[i]=ans-t[i];
for(int j=1;j<=n;j++)//枚举后继
{
if(g[i][j])
{
ma[i]=min(ma[i],dfsmax(j)-t[i]);
}
}
return ma[i];
}
void work()
{
tuopu();
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)
{
int ti=dfsmin(i)+t[i];
if (ans<ti) ans=ti;
}
printf("%d\n",ans);
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)
{
if(!v[i])
ma[i]=dfsmax(i);
}
for(int i=1;i<=n;i++)
{
if(mi[i]==ma[i])
printf("%d ",i);
}
}
int main()
{
init();
readdata();
work();
return 0;
}