【拓撲排序】 安排工作
阿新 • • 發佈:2018-12-13
【拓撲排序】·安排工作
初見安~
本題選自計蒜客(然而我並沒有在裡面搜到 )
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
題解
本題由於要最晚期限的時間的最大值 最小(這句話我都卡了好久才看懂
#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——