您的位置:首页 > 其它

BZOJ2109: [Noi2010]Plane 航空管制 解题报告

2016-10-16 10:57 375 查看
写完发现我真是想多了,一直觉得nm+n2logn过不了,结果轻松过去了

这题好像没有原题的第一问呀,不过有没有第一问都差不多…

感觉上这题每个数最前的位置不能一起求的,所以考虑一个一个求

如果只求第k个数最前的位置是什么的话,因为题意要求有些航班只能在一些航班之后起飞,所以先建一个拓扑图,但如果是按照位置1~n这样弄,每次在入度为0的点里面不知道选哪个点,因为有后效性(直接选限制时间最小的点是错的)。

所以考虑反向建一个拓扑图,时间从n推到1,将第k个数隔离出来不考虑,每次只要在入度为0的点里随便取一个限制时间≥当前时间的就行了,如果找不到这样的点,因为题目保证有解,所以这个位置只能放第k个数。。。。取点可以用一个优先队列弄一下。。。。

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<ctime>
#include<cmath>
#include<string>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<climits>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

const int maxn = 2100;
const int maxm = 110000;
struct edge
{
int y,nex;
}a[maxm];int len,fir[maxn];
int e[maxm][2];
void ins(int x,int y){len++;a[len].y=y;a[len].nex=fir[x];fir[x]=len;}
struct node
{
int x,d;
};
bool operator <(node x,node y){return x.d<y.d;}
priority_queue<node>q;
int d[maxn],dt[maxn],ans[maxn],dk[maxn];
int n,m;

int main()
{
memset(fir,0,sizeof fir); len=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&dk[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&e[i][0],&e[i][1]);
ins(e[i][1],e[i][0]);
d[e[i][0]]++;
}

for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
dt[i]=d[i];
if(!dt[i]&&i!=k)
{
node tmp;
tmp.x=i;tmp.d=dk[i];
q.push(tmp);
}
}
int nw=n;
while(!q.empty())
{
node x=q.top();q.pop();
if(x.d<nw) break;
for(int l=fir[x.x];l;l=a[l].nex)
{
dt[a[l].y]--;
if(!dt[a[l].y]&&a[l].y!=k)
{
node tmp;
tmp.x=a[l].y;tmp.d=dk[a[l].y];
q.push(tmp);
}
}
nw--;
}
ans[k]=nw;
while(!q.empty())q.pop();
}
for(int i=1;i<=n;i++)printf("%d ",ans[i]);
printf("\n");

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: