1. 程式人生 > >【拓撲排序】 安排工作

【拓撲排序】 安排工作

【拓撲排序】·安排工作

初見安~ 本題選自計蒜客(然而我並沒有在裡面搜到

Description

蒜頭君在公司有 n 件工作要做,現在已知每一件工作需要的時間 p 和完成這項工作的最晚期限 d。工作之間有 m 個限制關係,每一個限制關係是限制一項工作 x 一定要在另一項工作 y 之前完成。

蒜頭君工作壓力太大,不能按期限完成工作,他想要給自己安排一下工作的順序,使得每項工作拖最晚期限的時間的最大值最小。

即如果設編號為 i 的工作的完成時間為 ci 的話,要求安排一種工作順序,使得 max(ci−di,0) 最小,求出這個最小值。

Input

第一行兩個整數 n,m(1≤n≤104,1≤m≤105),表示同學數和要求數;

接下來 n 行,每行兩個整數 p,d,之間用一個空格隔開,表示每項工作需要的時間 p(1≤p≤104) 和完成這項工作的最晚期限 d(0≤d≤106);

再接下來 m 行,每行兩個整數 x,y ,表示編號為 x 的任務一定要在編號為 y 的任務之前完成,任務編號從 1 開始;

輸入保證一定能有一種安排方式可以滿足所有限制關係。

Output

輸出一行,包括 1 個整數,表示每項工作拖最晚期限的時間的最大值的最小值。若沒有一個工作被拖延,則輸出0。

Sample Input

2 1 1 0 2 1 1 2

Sample Output

2

題解

本題由於要最晚期限的時間的最大值 最小(這句話我都卡了好久才看懂

),且時間是會累加的,所以我們考慮的大致方向應為最小,然後找出哪項工作拖延的時間最長。 所以我們可以用到一個優先佇列——priority queue。拓撲排序時,由於存圖方式為連結串列(方便 ),所以存入優先佇列的為結構體,涉及到一個重定向操作——operator,讓佇列從小到大優先排序則重定向<。 下面是程式碼——(附解釋)

#include<bits/stdc++.h>
using namespace std;
const int N=100000;
int m,n;
int p[N],d[N],du[N];
int head[N],k=0;//頭結點
int ans=-32767,tme=0;
struct node
{
	int num,p,d,t;//序號,耗時,限時,時間
	node(int nn,int pp,int dd,int tt)
	{
		num=nn;p=pp;d=dd;t=tt;
	}
	bool operator < (const node &nd) const// 重定向
	{
		if(t!=nd.t) return t > nd.t;
		else return max(p - d , p + nd.p - nd.d) > max(nd.p - nd.d , p + nd.p -d);
	}
};

struct edge
{
	int v,next;
	edge(){}
	edge(int vv,int ee)
	{
		v=vv;next=ee;
	}
}e[N];

void add(int u,int v)//存邊
{
	e[k]=edge(v,head[u]);
	head[u]=k++;
	du[v]++;
}
void topo()
{
	priority_queue<node> q;//優先佇列
	for(int i=1;i<=n;i++)
	{
		if(du[i]==0) q.push(node(i,p[i],d[i],1));
	}
	
	while(!q.empty())
	{
		node now=q.top();
		q.pop();
		tme+=now.p;//累加時間
		ans=max(ans,tme-now.d);//此方法為預設時間儘量短,所以ans求在此情況下的最大值即可
		for(int i=head[now.num];~i;i=e[i].next)
		{
			int v=e[i].v;
			du[v]--;
			if(du[v]==0) q.push(node(v,p[v],d[v],now.t+1));
		}
	}
}

int main()
{
	memset(head,-1,sizeof head);//存結點時,以-1結尾表示到頭了。因為陣列沒有下標為-1的
	memset(du,0,sizeof du);
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>p[i]>>d[i];
	for(int i=1;i<=m;i++)
	{
		int a,b;
		cin>>a>>b;
		add(a,b);
	}
	topo();
	if(ans>=0) cout<<ans<<endl;
	else cout<<"0"<<endl;
	return 0;
}

迎評:) ——End——