Bzoj2535 [Noi2010]Plane 航空管制2
2016-09-25 13:50
344 查看
2535: [Noi2010]Plane 航空管制2
Time Limit: 10 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 722 Solved: 456
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个整数,表示一个可行的起飞序列,相邻两个整数用空格分隔。
输入数据保证至少存在一个可行的起飞序列。如果存在多个可行的方案,输出任
意一个即可。
第二行包含 n个整数 t1, t2, „, tn,其中 ti表示航班i可能的最小起飞序
号,相邻两个整数用空格分隔。
Sample Input
5 54 5 2 5 4
1 2
3 2
5 1
3 4
3 1
Sample Output
3 5 1 4 23 4 1 2 1
HINT
Source
反向存边,并将每架飞机的起飞限制x改成n-x,就将问题转化成一个求飞机最晚起飞时间的问题,用拓扑排序可解。
如何求每架飞机的最小起飞次序? 在新问题中,每次限制不起飞某架飞机p,而将其他能飞的飞机都飞出去(拓扑排序时不处理p结点,让p连出去的边都保留下来),此时飞机p必须起飞了,这个时间就是它在新问题中的最晚起飞时间,也就是原问题中的最早起飞时间。
/************************************************************** Problem: 2535 User: SilverN Language: C++ Result: Accepted Time:1296 ms Memory:3284 kb ****************************************************************/ #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<queue> using namespace std; const int mxn=30000; int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } //bas int n,m; //plane struct plane{ int id; int limit; }p[mxn]; int cmp(plane a,plane b){return a.limit<b.limit;} //edge struct edge{//存边,若a必须早于b起飞,则存一条从b到a的边 int v; int nxt; }e[mxn]; int hd[mxn],mct=0; void add_edge(int u,int v){ e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct; return; } //拓扑排序 int limit[mxn]; int ind[mxn]; int top=0; int ans[mxn]; int deg[mxn]; /* queue<int>q; void solve(int x){ memcpy(deg,ind,sizeof ind); while(!q.empty()) q.pop(); int i,j; top=0; int pos=1; for(i=1;i<=n;i++){ for(;pos<=n && p[pos].limit<i;pos++){ int v=p[pos].id; if(!deg[v] && x!=v){ q.push(v); ans[++top]=v; } } if(q.empty())break; int u=q.front();q.pop(); for(j=hd[u];j;j=e[j].nxt){ int v=e[j].v; deg[v]--; if(!deg[v] && v!=x && limit[v]<i){ q.push(v); ans[++top]=v; } } } return; }*/ int head,tail; int q[mxn<<3]; void solve(int x){//不安排x int pos,i,j,u,v; memcpy(deg,ind,sizeof ind); head=tail=0; for(i=1,pos=1;i<=n;i++){ for(;pos<=n && p[pos].limit<i;pos++){ int v=p[pos].id; if(!deg[v] && x!=v){ // printf("test2:%d %d\n",deg[v],v); q[++tail]=v; } } if(head<tail){ u=q[++head]; for(j=hd[u];j;j=e[j].nxt){ int v=e[j].v; deg[v]--; if(!deg[v] && v!=x && limit[v]<i){ // printf("test3:%d %d\n",deg[v],v); q[++tail]=v; } } } else return; } return; } //main int main(){ int i,j; n=read();m=read(); for(i=1;i<=n;i++){ p[i].limit=read(); p[i].limit=n-p[i].limit; p[i].id=i; limit[i]=p[i].limit; } int u,v; sort(p+1,p+n+1,cmp); for(i=1;i<=m;i++){ u=read();v=read(); ind[u]++; add_edge(v,u); } solve(0); for(i=tail;i;i--)printf("%d ",q[i]); // for(i=top;i;i--)printf("%d ",ans[i]); printf("\n"); for(i=1;i<=n;i++){ solve(i); printf("%d ",n-tail); } return 0; }
相关文章推荐
- BZOJ2535 [Noi2010]Plane 航空管制2
- BZOJ2535: [Noi2010]Plane 航空管制2
- 2109&2535: [Noi2010]Plane 航空管制 - BZOJ
- BZOJ2535 [Noi2010]Plane 航空管制 【贪心 + 堆】
- bzoj2535 [Noi2010]Plane 航空管制2 [贪心+堆]
- bzoj2535: [Noi2010]Plane 航空管制
- [拓扑排序] BZOJ 2535 [Noi2010]Plane 航空管制2 & 2109 [Noi2010]Plane 航空管制
- [BZOJ 2109/BZOJ 2535][NOI 2010]航空管制(贪心)
- BZOJ2109: [Noi2010]Plane 航空管制 解题报告
- bzoj 2109: [Noi2010]Plane 航空管制
- BZOJ 2535|BZOJ 2109|BZOJ 2008|NOI 2010|航空管制|拓扑排序
- bzoj 2109: [Noi2010]Plane 航空管制 贪心+拓扑排序
- bzoj2109 [Noi2010]Plane 航空管制 贪心 拓补排序
- bzoj2535 [Noi2010]航空管制
- 2535: [Noi2010]Plane 航空管制2
- BZOJ2109 [Noi2010]Plane 航空管制
- [Noi2010]Plane 航空管制
- BZOJ2109: [Noi2010]Plane 航空管制
- BZOJ 2535 Plane 航空管制2
- BZOJ 2535 Plane 航空管制2