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{Cj-dj, 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 ≤ i, j ≤ 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
题意:
n个任务,每一个任务具有处理时间pj和期限dj,m对 (i j) 表要想完成 j 任务,则先完成 i 任务)m对 (i j) 表要想完成 j 任务,则先完成 i 任务),使得所有情况中min{max{Cj-dj, 0}}的值最小。输出一个完成任务的先后顺序,满足情况可能有多种,只要输出其中一种即可。
分析:这题只要看出先做di越小的越好,然后用一个拓扑排序(优先选择di小的)就欧克了
证明(但我不会,网上的证明):
一、通俗点
因为对于最小的那个dj是不变的,那么如果先加工其他的,那么cj就会增大,从而cj - dj就会增大,所以要先加工dj小的。
二、严谨点
原文:https://blog.csdn.net/chm517/article/details/9291227
假设同一时刻t有两个活动i,j可做,
先做i s1 =max(t+pi-di,t+pi+pj-dj,0)
先做j s2 =max(t+pj-dj,t+pi+pj-di,0)
//此处省不省略0对证明不影响只对s1,s2影响。
//举例来说,省略0是超时完成要扣钱,提前完成有奖金
//而不省略0是是超时完成要扣钱,提前完成没有事件发生
1) s1中 t+pi-di>t+pi+pj-dj
s2中 t+pj-dj>t+pi+pj-di
有0>pi+pj,显而不符
2)s1中 t+pi-di>t+pi+pj-dj,即-di>pj-dj ,可推出di<dj-pj<dj
s2中 t+pj-dj<=t+pi+pj-di
s2-s1=pj,显然s1<=s2
3)s1中 t+pi-di<=t+pi+pj-dj,
s2中 t+pj-dj>t+pi+pj-di 即-dj>pi-di ,推出dj<di-pi<di
s2-s1=-pj,显然s2<=s1
4) s1中 t+pi-di<t+pi+pj-dj
s2中 t+pj-dj<t+pi+pj-di
s2-s1=dj-di,结果与(2)(3)相符
因此,假设同一时刻t有两个活动i,j可做,应优先做d值小的(与p无关)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N=50005;
vector<int> G[N];
int in[N],d[N];
vector<int>path;
int n;
int cnt;
struct node
{
int id,d;
friend bool operator<(node a,node b)
{
return b.d>a.d;
}
}x,y;
int topo()
{
priority_queue<node>Q;
for(int i=1;i<=n;i++)
{
if(in[i]==0)
{
x.id=i;
x.d=d[i];
Q.push(x);
}
}
while(!Q.empty())
{
y= Q.top();
Q.pop();
path.push_back(y.id);
for(int i=0;i<G[y.id].size();i++)
{
in[G[y.id][i]]--;
if(in[G[y.id][i]]==0)
{
x.id=G[y.id][i];
x.d=d[G[y.id][i]];
Q.push(x);
}
}
}
}
int main()
{
int m;
while(scanf("%d",&n)!=-1)
{
memset(in,0,sizeof(in));
for(int i=0;i<=n;i++)
G[i].clear();
path.clear();
for(int i = 1; i <= n; i++)
{
int a;
scanf("%d%d",&a,&d[i]);
}
scanf("%d",&m);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
G[b].push_back(a);
in[a]++;
}
topo();
for(int i=n-1;i>=0;i--)
printf("%d\n", path[i]);
}
return 0;
}