Evanyou Blog 彩带

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了。

代码:

 

#include<bits/stdc++.h>
#define il inline
#define ll long long
using namespace std;
const int N=10005,M=100005;
int n,m,ans,t[N],a[N],cost[N],cnt,to[M],net[M],h[N],rd[N];
il void add(int x,int y)
{
    to[++cnt]=y,net[cnt]=h[x],h[x]=cnt,rd[y]++;
}
il int gi()
{
    int a=0;char x=getchar();bool f=0;
    while((x<'0'||x>'9')&&x!='-')x=getchar();
    if(x=='-')x=getchar(),f=1;
    while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
    return f?-a:a;
}
il void topsort()
{
    queue<int>q;
    for(int i=1;i<=n;i++)
        if(!rd[i])q.push(i);
    while(!q.empty()){
        int x=q.front();q.pop();
        cost[x]=a[x]+t[x];
        ans=max(ans,cost[x]);
        for(int i=h[x];i;i=net[i]){
            rd[to[i]]--;
            a[to[i]]=max(a[to[i]],cost[x]);
            if(!rd[to[i]])q.push(to[i]);
        }
    }
}
int main()
{
    n=gi(),m=gi();
    //cout<<n<<m<<endl;
    for(int i=1;i<=n;i++)t[i]=gi();
    int u,v;
    while(m--){
        u=gi(),v=gi();
        add(v,u);
    }
    topsort();
    cout<<ans;
    return 0;
}

 

 

 

 

posted @ 2018-04-07 20:58  five20  阅读(460)  评论(0编辑  收藏  举报
Live2D