BZOJ2109: [Noi2010]Plane 航空管制

Description

世博期間,上海的航空客運量大大超過了平時,隨之而來的航空管制也頻頻 發生。最近,小X就由於航空管制,連續兩次在機場被延誤超過了兩小時。對此, 小X表示很不滿意。 在此次來煙臺的路上,小 X不幸又一次碰上了航空管制。因而小 X開始思考 關於航空管制的問題。 假設目前被延誤航班共有 n個,編號爲 1至n。機場只有一條起飛跑道,所 有的航班需按某個順序依次起飛(稱這個順序爲起飛序列)。定義一個航班的起 飛序號爲該航班在起飛序列中的位置,便是第幾個起飛的航班。 起飛序列還存在兩類限制條件:  第一類(最晚起飛時間限制):編號爲 i的航班起飛序號不得超過 ki;  第二類(相對起飛順序限制):存在一些相對起飛順序限制(a, b),表示 航班 a的起飛時間必須早於航班 b,即航班 a的起飛序號必須小於航班 b 的起飛序號。 小X 思考的第一個問題是,若給定以上兩類限制條件,是否能夠計算出一個 可行的起飛序列。第二個問題則是,在考慮兩類限制條件的狀況下,如何求出每 個航班在全部可行的起飛序列中的最小起飛序號。

Input

第一行包含兩個正整數 n和m,n表示航班數目,m表示 第二類限制條件(相對起飛順序限制)的數目。 第二行包含 n個正整數 k1, k2, „, kn。 接下來 m行,每行兩個正整數 a和b,表示一對相對起飛順序限制(a, b), 其中1≤a,b≤n, 表示航班 a必須先於航班 b起飛。

Output

包含 n個整數 t1, t2, „, tn,其中 ti表示航班i可能的最小起飛序 號,相鄰兩個整數用空格分隔。

Sample Input


5 5
4 5 2 5 4
1 2
3 2
5 1
3 4
3 1

Sample Output


3 4 1 2 1

在樣例 1 中:
起飛序列 3 5 1 4 2 知足了全部的限制條件,全部知足條件的起飛序列有:
3 4 5 1 2 3 5 1 2 4 3 5 1 4 2 3 5 4 1 2
5 3 1 2 4 5 3 1 4 2 5 3 4 1 2
因爲存在(5, 1)和(3, 1)兩個限制,航班1只能安排在航班 5和3以後,故最先
起飛時間爲3,其餘航班相似。


對於30%數據:n≤10;
對於60%數據:n≤500;
對於100%數據:n≤2,000,m≤10,000。
 
咱們發現這個問題直接作比較困難,考慮倒過來作。
將原圖反向,最晚時刻限定改爲最先時刻限定,不難證實新問題的解與原題中的解一一對應。
然而新問題好作多了,航班k出發的最晚時刻能夠考慮在拓撲排序的時候先無論k航班,直到當前隊列中沒有元素了再將k加入,不難證實這就是航班k出發的最晚時刻,即原問題中航班k出發的最先時刻。
時間複雜度爲O(nm)。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
	if(head==tail) {
		int l=fread(buffer,1,BufferSize,stdin);
		tail=(head=buffer)+l;
	}
	return *head++;
}
inline int read() {
    int x=0,f=1;char c=Getchar();
    for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=2010;
const int maxm=10010;
int n,m,ans[maxn];
struct Pair {
	int v,p;
	bool operator < (const Pair& ths) const {return v<ths.v;}
}A[maxn];
int p[maxn],q[maxn],first[maxn],deg[maxn],in[maxn],next[maxm],to[maxm],e;
void AddEdge(int u,int v) {deg[v]++;to[++e]=v;next[e]=first[u];first[u]=e;}
int solve(int k) {
	rep(i,1,n) in[i]=deg[i];
	int cur=1,l=1,r=0,x,res;
	rep(j,1,n) {
		while(cur<=n&&A[cur].v<=j) {
			if(!in[A[cur].p]&&A[cur].p!=k) q[++r]=A[cur].p;
			cur++;
		}
		if(l<=r) x=q[l++]; else return j;
		ans[j]=x;
		ren {
			in[to[i]]--;
			if(!in[to[i]]&&p[to[i]]<=j&&to[i]!=k) q[++r]=to[i];
		}
	}
	return res;
}
int main() {
	n=read();m=read();
	rep(i,1,n) A[i]=(Pair){p[i]=n-read()+1,i};
	rep(i,1,m) AddEdge(read(),read()); 
	sort(A+1,A+n+1);
	rep(i,1,n) printf("%d ",n-solve(i)+1);
	return 0;
}
相關文章
相關標籤/搜索