主要算法
拓扑排序+动态规划
思路
首先做一遍拓扑排序,
每当有一个点入度为0时,
我们就从它的父亲中选一个最大的时间
作为完成这个工程之前所需的时间。
最后统计一下就行。
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int a[100010],ls[100010],dl[100010],v[100010],f[100010],d[100010];
int n,x,tot,ans;
struct node
{
int y,next;
}w[100010];
void ljb(int x,int y)
{
w[++tot]=(node){
y,ls[x]};
ls[x]=tot;
}
void tp()
{
int tl=0,hd=0;
for(int i=1; i<=n; i++)
if(d[i]==0)
dl[++tl]=i,v[i]=1,f[i]=a[i];
while(hd<tl)
{
hd++;
int y=dl[hd];
for(int i=ls[y]; i; i=w[i].next) //找每个儿子
{
int yy=w[i].y;
if(v[yy]!=0)
continue;
d[yy]--;
f[yy]=max(f[yy],f[y]); //动态转移方程
if(d[yy]==0)
dl[++tl]=yy,v[yy]=1,f[yy]+=a[yy];
}
}
}
int main()
{
cin>>n;
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
if(j==i)
continue;
scanf("%d",&x);
if(x==1)
{
ljb(j,i);
d[i]++;
}
}
tp();
for(int i=1; i<=n; i++)
{
if(d[i]!=0) //存在环
{
cout<<-1;
return 0;
}
ans=max(ans,f[i]);
}
cout<<ans;
return 0;
}