SSL2876 工程【拓扑排序】

在这里插入图片描述

主要算法

拓扑排序+动态规划

思路

首先做一遍拓扑排序,
每当有一个点入度为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;
}

猜你喜欢

转载自blog.csdn.net/Jackma_mayichao/article/details/108048079