P3074 [USACO13FEB]牛奶調度Milk Scheduling
題目描述
Farmer John‘s N cows (1 <= N <= 10,000) are conveniently numbered 1..N. Each cow i takes T(i) units of time to milk. Unfortunately, some cows must be milked before others, owing to the layout of FJ‘s barn. If cow A must be milked before cow B, then FJ needs to completely finish milking A before he can start milking B.
In order to milk his cows as quickly as possible, FJ has hired a large number of farmhands to help with the task -- enough to milk any number of cows at the same time. However, even though cows can be milked at the same time, there is a limit to how quickly the entire process can proceed due to the constraints requiring certain cows to be milked before others. Please help FJ compute the minimum total time the milking process must take.
農民約翰有N頭奶牛(1<=N<=10,000),編號為1...N。每一頭奶牛需要T(i)單位的時間來擠奶。不幸的是,由於FJ的倉庫布局,一些奶牛要在別的牛之前擠奶。比如說,如果奶牛A必須在奶牛B前擠奶,FJ就需要在給奶牛B擠奶前結束給奶牛A的擠奶。
為了盡量完成擠奶任務,FJ聘請了一大批雇工協助任務——同一時刻足夠去給任意數量的奶牛擠奶。然而,盡管奶牛可以同時擠奶,但仍需要滿足以上的擠奶先後順序。請幫助FJ計算擠奶過程中的最小總時間。
輸入輸出格式
輸入格式:* Line 1: Two space-separated integers: N (the number of cows) and M (the number of milking constraints; 1 <= M <= 50,000).
* Lines 2..1+N: Line i+1 contains the value of T(i) (1 <= T(i) <= 100,000).
* Lines 2+N..1+N+M: Each line contains two space-separated integers A and B, indicating that cow A must be fully milked before one can start milking cow B. These constraints will never form a cycle, so a solution is always possible.
輸出格式:* Line 1: The minimum amount of time required to milk all cows.
輸入輸出樣例
輸入樣例#1:3 1
10
5
6
3 2
輸出樣例#1:
11
說明
There are 3 cows. The time required to milk each cow is 10, 5, and 6, respectively. Cow 3 must be fully milked before we can start milking cow 2.
Cows 1 and 3 can initially be milked at the same time. When cow 3 is finished with milking, cow 2 can then begin. All cows are finished milking after 11 units of time have elapsed.
Solution:
解釋一手題意:本題就是一棵樹(或者森林)中,從每個rd為0的點來走一條路徑(需要時間),輸出最長的時間。
本題描述中有一句話很重要(直接得出算法):"若b在a前面,則b必須先擠奶,再去給a擠奶"。
於是就有了上面的一句話題意,一個根節點要在它的多個兒子節點前被訪問,然後找出它到各兒子節點的最長的時間,就是訪問該樹的最少時間。(畫個圖自己理解吧,語文太差,描述不好)
於是想到拓撲排序。於是直接統計入度,在拓撲排序時加兩條語句維護每條路徑的最長時間就OK了。
代碼:
1 // luogu-judger-enable-o2 2 #include<bits/stdc++.h> 3 #define il inline 4 #define ll long long 5 using namespace std; 6 const int N=10005,M=100005; 7 int n,m,ans,t[N],a[N],cost[N],cnt,to[M],net[M],h[N],rd[N]; 8 il void add(int x,int y) 9 { 10 to[++cnt]=y,net[cnt]=h[x],h[x]=cnt,rd[y]++; 11 } 12 il int gi() 13 { 14 int a=0;char x=getchar();bool f=0; 15 while((x<‘0‘||x>‘9‘)&&x!=‘-‘)x=getchar(); 16 if(x==‘-‘)x=getchar(),f=1; 17 while(x>=‘0‘&&x<=‘9‘)a=a*10+x-48,x=getchar(); 18 return f?-a:a; 19 } 20 il void topsort() 21 { 22 queue<int>q; 23 for(int i=1;i<=n;i++) 24 if(!rd[i])q.push(i); 25 while(!q.empty()){ 26 int x=q.front();q.pop(); 27 cost[x]=a[x]+t[x]; 28 ans=max(ans,cost[x]); 29 for(int i=h[x];i;i=net[i]){ 30 rd[to[i]]--; 31 a[to[i]]=max(a[to[i]],cost[x]); 32 if(!rd[to[i]])q.push(to[i]); 33 } 34 } 35 } 36 int main() 37 { 38 n=gi(),m=gi(); 39 //cout<<n<<m<<endl; 40 for(int i=1;i<=n;i++)t[i]=gi(); 41 int u,v; 42 while(m--){ 43 u=gi(),v=gi(); 44 add(v,u); 45 } 46 topsort(); 47 cout<<ans; 48 return 0; 49 }
P3074 [USACO13FEB]牛奶調度Milk Scheduling