POJ3553 Task schedule (拓扑排序+优先队列)经典

Task schedule

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 306 Accepted: 193 Special Judge

Description

There are n preemptive jobs to be processed on a single machine. Each job j has a processing time pj and deadline dj. Preemptive constrains are specified by oriented graph without cycles. Arc (i,j) in this graph means that job i has to be processed before job j. A solution is specified by a sequence of the jobs. For any solution the completion time Cj is easily determined.

The objective is to find the optimal solution in order to minimize

max{Cjdj, 0}.

Input

The first line contains a single integer n, 1 ≤ n ≤ 50000. Each of the next n lines contains two integers pj and dj, 0 ≤ pj ≤ 1000, 0 ≤ dj ≤ 1000000, separated by one or more spaces. Line n+2 contains an integer m (number of arcs), 0 ≤ m ≤ 10*n. Each of the next m lines contains two integers i and j, 1 ≤ ij ≤ n.

Output

Each of the n lines contains integer i (number of job in the optimal sequence).

Sample Input

2
4 1
4 0
1
1 2

Sample Output

1
2

Source

Northeastern Europe 2003, Western Subregion 题意看了好久都没能明白,最后终于理解了。 在网上看到的都是用  贪心算法+DFS  过的。 题意:完成所有的任务后,问 怎样按照一定的时间先后顺序去完成所有任务(每个任务有一个完成处理的时间,只有一台机器,且机器每次只能处理一个任务,m对 (i   j) 表要想完成 j 任务,则先完成 i 任务),使得所有情况中min{
max{
Cj

dj
, 0}}的值最小。输出一个完成任务的先后顺序,满足情况可能有多种,只要输出其中一种即可。

解题:我们可以反向思考,最后完成所有任务的总时间是确定的,那么只要判断哪一任务在最后处理(最后处理的任务有 一特点:出度为0),要想
max{
Cj

dj
, 0}最小,则找出度为0的dj  最大的点,当确定了一个最终输出的点后,就可以把该点及有关的信息在图中删除,之后重复上述步骤一个一个确定点,最后得到一个序列。那么我们只要反向建图,则出度为0的点变成了入度为0的点,用优先队列处理,从队列中取出的点,先用数组存入,最后处理完了,逆向输出序列。

#include<stdio.h>
#include<queue>
#include<vector>
using namespace std;
const int N = 50005 ;
struct node
{
    int id,d;
    friend bool operator<(node a,node b)
    {
        return b.d>a.d;
    }
};

vector<int>mapt[N];
int path[N],in[N],d[N];

void print(int n)
{
    while(n--)
    {
        printf("%d\n",path[n]);
    }
}
void tope(int n)
{
    int k=0;
    priority_queue<node>q;
    node pre,now;

    for(int i = 1; i <= n; i++)
    if(in[i]==0)
    {
        now.d = d[i]; now.id = i; q.push(now);
    }
    while(!q.empty())
    {
        pre = q.top(); q.pop();
        path[k++] = pre.id;
        int len = mapt[pre.id].size();
        for(int i = 0 ;i < len; i++)
        {
            now.id = mapt[pre.id][i];
            now.d = d[now.id];
            in[now.id]--;
            if(in[now.id]==0)
            {
                q.push(now);
            }
        }
    }
    print(k);
}
int main()
{
    int n,m,a,b;
    while(scanf("%d",&n)>0)
    {
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d",&a,&d[i]);
            in[i] = 0;
            mapt[i].clear();
        }
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d",&a,&b);
            mapt[b].push_back(a);
            in[a]++;
        }
        tope(n);
    }
}
    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/u010372095/article/details/45318097
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞