题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2535

https://www.lydsy.com/JudgeOnline/problem.php?id=2109

这个题,如果正着考虑,也就是先考虑放在前面的再考虑放在后面的,决策时会有矛盾;
也就是,如果要求 pos[a] < pos[b],则先考虑放 a,因为许多点放在 a 后面,所以 a 尽量往前放可以给它们留出空位;
但又有限制最晚起飞时间,那么先考虑的 a 应该尽量放在靠近它最晚起飞时间的地方,以免后面的点无法满足起飞时间的限制;
于是尽量往前放和尽量往后放形成了矛盾,无法决策;
所以需要转化一个限制,不妨对于 pos[a] < pos[b],先决策 b;
于是两个限制合起来的要求就都变成尽量往后放了(真神奇);
所以我们就这样倒着做,一定能得到合法的序列;
然后考虑每个点的可能最前位置,其实就是做的过程中把这个点以及它限制的点都暂时去掉,让其他点放好,那么不能再放的时候就意味着只有放上这个点才能继续,这时这个点按刚才做法找到的位置就是它的最前位置(其他点已经尽量把它的可行位置挤到前面了);
注意放点位置是最晚起飞时间和限制它的点的起飞时间取 min 的!
注意答案是起飞序列!而不是每个点的起飞位置!
如果用 set 找某位置前面第一个空位会很慢,还是并查集好。
代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
int const xn=,xm=;
int n,m,hd[xn],ct,to[xm],nxt[xm],deg[xn],tmp[xn],ans[xn],d[xn],mn[xn];
struct N{
int v,id;
N(int v=,int i=):v(v),id(i) {}
};
queue<int>q;
set<int>st;
set<int>::iterator it;
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return f?ret:-ret;
}
void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
void topo(int nw)
{
for(int i=;i<=n;i++)
{
mn[i]=min(n,d[i]); tmp[i]=deg[i];
if(!tmp[i]&&i!=nw)q.push(i);
}
while(q.size())
{
int x=q.front(); q.pop();
it=st.lower_bound(n-mn[x]+);
int tim=*it;
//ans[x]=n-tim+1; //!!!
ans[n-tim+]=x;
st.erase(tim);
for(int i=hd[x],u;i;i=nxt[i])
{
if((u=to[i])==nw)continue;
tmp[u]--; mn[u]=min(mn[u],mn[x]);//!!
if(!tmp[u])q.push(u);
}
}
}
int solve(int x)
{
st.clear();
for(int i=;i<=n;i++)st.insert(i);
topo(x);
it=st.lower_bound(n-d[x]+);
return n-*it+;
}
int main()
{
n=rd(); m=rd();
for(int i=;i<=n;i++)d[i]=rd(),st.insert(i);
for(int i=,x,y;i<=m;i++)x=rd(),y=rd(),add(y,x),deg[x]++;
topo();
for(int i=;i<=n;i++)printf("%d ",ans[i]); puts("");
for(int i=;i<=n;i++)printf("%d ",solve(i)); puts("");
return ;
}

set

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int const xn=,xm=;
int n,m,hd[xn],ct,to[xm],nxt[xm],deg[xn],tmp[xn],ans[xn],d[xn],mn[xn];
int fa[xn],q[xn];
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return f?ret:-ret;
}
void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void topo(int nw)
{
int cnt=;
for(int i=;i<=n;i++)
{
mn[i]=min(n,d[i]); tmp[i]=deg[i]; fa[i]=i;
if(!tmp[i]&&i!=nw)q[++cnt]=i;
}
while(cnt)
{
int x=q[cnt--]; int tim=find(mn[x]);
ans[tim]=x; fa[tim]=tim-;
for(int i=hd[x],u;i;i=nxt[i])
{
if((u=to[i])==nw)continue;
tmp[u]--; mn[u]=min(mn[u],mn[x]);//!!
if(!tmp[u])q[++cnt]=u;
}
}
}
int solve(int x)
{
topo(x); return find(d[x]);
}
int main()
{
n=rd(); m=rd();
for(int i=;i<=n;i++)d[i]=rd();
for(int i=,x,y;i<=m;i++)x=rd(),y=rd(),add(y,x),deg[x]++;
topo();
for(int i=;i<=n;i++)printf("%d ",ans[i]); puts("");
for(int i=;i<=n;i++)printf("%d ",solve(i)); puts("");
return ;
}

bzoj 2535 & bzoj 2109 航空管制 —— 贪心+拓扑序的更多相关文章

  1. BZOJ 2535: [Noi2010]Plane 航空管制2

    Description 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此,小X表示很不满意. 在这次来烟台的路上 ...

  2. [BZOJ2109][NOI2010]航空管制(贪心+拓扑)

    2109: [Noi2010]Plane 航空管制 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1227  Solved: 510[Submit][ ...

  3. bzoj 2535: [Noi2010]Plane 航空管制2【拓扑排序+堆】

    有个容易混的概念就是第一问的答案不是k[i]字典序最小即可,是要求k[i]大的尽量靠后,因为这里前面选的时候是对后面有影响的(比如两条链a->b c->d,ka=4,kb=2,kc=3,k ...

  4. bzoj 2535 && bzoj 2109 [Noi2010]Plane 航空管制——贪心

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2535 https://www.lydsy.com/JudgeOnline/problem.p ...

  5. 2109&2535: [Noi2010]Plane 航空管制 - BZOJ

    Description世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此,小X表示很不满意. 在这次来烟台的路上, ...

  6. BZOJ 2109 航空管制(拓扑排序+贪心)

    绝世好题啊.. 题意:给出一个DAG,和每个点要求出现在这个DAG里面的拓扑排序的位置<=ti,求出所有可能的拓扑排序里面每个点出现的位置的最小值. 正着做不好做,考虑反着做,建立这个图的反图. ...

  7. BZOJ2535: [Noi2010]Plane 航空管制2(拓扑排序 贪心)

    题意 题目链接 Sol 非常妙的一道题. 首先不难想到拓扑排序,但是直接对原图按\(k\)从小到大拓扑排序是错的.因为当前的\(k\)大并不意味着后面的点\(k\)也大 但是在反图上按\(k\)从大到 ...

  8. BZOJ.2109.[NOI2010]航空管制(拓扑 贪心)

    题目链接 双倍经验(没有第一问) \(Description\) \(Solution\) 第一问拓扑排序即可. 第二问,即让一个元素在拓扑序中尽量靠前,好像不好做. 但是可以让一个元素出现尽量靠后. ...

  9. bzoj 2109: [Noi2010]Plane 航空管制

    Description 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频 发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此, 小X表示很不满意. 在这次来烟台的 ...

随机推荐

  1. 解决 ie 返回json提示下载 ResponseEntity方法

    js 配合java  springMVC后台,成功后返回消息,chrom ff都正常,只有IE提交后返回的JSON提示下载,查看类型 application/json  google后发现原来是IE不 ...

  2. ADO.NET概述

    xml这类文件它是.net变成环境中优先使用的数据访问借口. ADO.NET传输的数据都是XML格式的 ADO.NET是一组用于和数据源惊醒交互的面向对象类库 数据源:通常是各种数据库,但文本.exc ...

  3. xpath取最后一个元素

    取xpath最后一个book元素 book[last()] 取xpath最后第二个book元素 book[last()-1]

  4. LeetCode:零钱兑换【322】【DP】

    LeetCode:零钱兑换[322][DP] 题目描述 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成 ...

  5. Data Structure Array: Given an array of of size n and a number k, find all elements that appear more than n/k times

    http://www.geeksforgeeks.org/given-an-array-of-of-size-n-finds-all-the-elements-that-appear-more-tha ...

  6. 第三章 python中的字符串

    一.字符串的基本操作 所有标准的序列操作对字符串同样适用,如索引.分片.乘法.判断成员是否存在.求长度.最大值和最小值等.记住一点,字符串是不可变的. 二.字符串中重要的方法 1.find(subst ...

  7. OpenStack Neutron 之 Load Balance

    OpenStack Neutron 之 Load Balance 负载均衡(Load Balance)是 OpenStack Neutron 支持的功能之一.负载均衡能够将网络请求分发到多个实际处理请 ...

  8. 文字溢出 省略css

     overflow:hidden;   text-overflow:ellipsis;   -o-text-overflow:ellipsis; white-space:nowrap;   

  9. Unity Json解析IPA

    今天看到一个unity 自带的解析json的IPA,感觉比litjson好用很多,废话不多,上代码 using System.Collections; using System.Collections ...

  10. running a background task over ssh

    原文: Why does running a background task over ssh fail if a pseudo-tty is allocated? 问题: I've recently ...