P1113 雜務(貪心)

題目描述

鏈接:https://www.luogu.org/problemnew/show/P1113
John的農場在給奶牛擠奶前有很多雜務要完成,每一項雜務都需要一定的時間來完成它。比如:他們要將奶牛集合起來,將他們趕進牛棚,爲奶牛清洗乳房以及一些其它工作。儘早將所有雜務完成是必要的,因爲這樣纔有更多時間擠出更多的牛奶。當然,有些雜務必須在另一些雜務完成的情況下才能進行。比如:只有將奶牛趕進牛棚才能開始爲它清洗乳房,還有在未給奶牛清洗乳房之前不能擠奶。我們把這些工作稱爲完成本項工作的準備工作。至少有一項雜務不要求有準備工作,這個可以最早着手完成的工作,標記爲雜務1。John有需要完成的n個雜務的清單,並且這份清單是有一定順序的,雜務k(k>1)的準備工作只可能在雜務11至k-1中。

寫一個程序從11到nn讀入每個雜務的工作說明。計算出所有雜務都被完成的最短時間。當然互相沒有關係的雜務可以同時工作,並且,你可以假定John的農場有足夠多的工人來同時完成任意多項任務。

輸入格式

第1行:一個整數n,必須完成的雜務的數目(3≤n≤10,000);

第2至(n+1)行: 共有n行,每行有一些用1個空格隔開的整數,分別表示:

  • 工作序號(1至n,在輸入文件中是有序的);

  • 完成工作所需要的時間len(1≤len≤100);

  • 一些必須完成的準備工作,總數不超過100個,由一個數字0結束。有些雜務沒有需要準備的工作只描述一個單獨的0,整個輸入文件中不會出現多餘的空格。

輸出格式

一個整數,表示完成所有雜務所需的最短時間。

輸入輸出樣例

輸入

7
1 5 0
2 2 1 0
3 3 2 0
4 6 1 0
5 1 2 4 0
6 8 2 4 0
7 4 3 5 6 0

輸出

23

思路

在這裏插入圖片描述
如圖,可以看見該圖是一個有點權的有向圖,個人的思想是貪心:用一個數組來記錄每個點的最大總權值,以5號點爲例子,先找到其父親(即先決條件)中最大總權值最大的節點,用該點的最大總權值加上5號節點的權值即爲5號節點的最大總權值。
最後找到所有沒有出度的點(在該圖中即爲7號節點),比較所有無出度的節點中最大總權值的最大值,即爲所求,附代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
	int t,need[105],size,num;
}a[10005];
bool f[10005],f1[10005];//f1[i]表示i個節點是否已求出最大總權值,1表示已求出,0表示未求出
int read(){
	int f=1,s=0;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-f;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=(s<<3)+(s<<1)+ch-'0';
		ch=getchar();
	}
	return s*f;
}
int max(int x,int y){
	return x > y ? x : y;
}
int query(int x){
	if(f1[x])
	return a[x].t;
	f1[x]=1;
	int fjy=0;
	for(int i=1;i<=a[x].size;i++)
		fjy=max(fjy,query(a[x].need[i]));
	a[x].t+=fjy;
	return a[x].t;//a[i].t輸入時爲i節點的權值,後期更新爲
}
int n,jie,m,ans;
int main()
{
	memset(f1,0,sizeof(f1));
	n=read();
	for(int i=1;i<=n;i++)
	{
		a[i].num=read(),a[i].t=read();
		m=read();
		while(m!=0){
			a[i].size++;
			a[i].need[a[i].size]=m;
			f[m]=1;
			m=read();
		}
	}
	for(int i=1;i<=n;i++){
		if(!f[i])
			ans=max(ans,query(i));
	}
	printf("%d",ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章