解题:NOI 2010 航空管制

题面

常见的套路与不常见的套路

第一问是常见的套路,建反边用优先队列跑拓扑排序

第二问是不常见的套路,如何判断一个点最早什么时候起飞?先不加它来拓扑排序,直到拓扑排序不能进行下去了,这个时刻就是它必须加入的时刻。因为我们是反着做的,所以这样求出来的就是最早时刻。

 1 // luogu-judger-enable-o2
 2 #include<queue>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=2005,M=10005;
 8 int n,m,t1,t2,cnt,top;
 9 int p[N],noww[M],goal[M];
10 int mem[N],deg[N],lst[N],stk[N],que[N];
11 priority_queue<pair<int,int> > hp;
12 void Clean()
13 {
14     priority_queue<pair<int,int> > tmp;
15     swap(hp,tmp);
16 }
17 void Link(int f,int t)
18 {
19     noww[++cnt]=p[f],p[f]=cnt;
20     goal[cnt]=t,mem[t]++;
21 }
22 int Solve(int nde)
23 {
24     Clean();
25     for(int i=1;i<=n;i++) 
26         if(!(deg[i]=mem[i])&&i!=nde) 
27             hp.push(make_pair(lst[i],i));
28     deg[nde]=n;
29     for(int i=n;i;i--)
30     {
31         if(hp.empty()) return i;
32         pair<int,int> tn=hp.top(); hp.pop(); 
33         if(tn.first<i) return i;
34         for(int i=p[tn.second];i;i=noww[i])
35             if(!(--deg[goal[i]]))
36                 hp.push(make_pair(lst[goal[i]],goal[i]));
37     }
38 }
39 int main()
40 {
41     scanf("%d%d",&n,&m);
42     for(int i=1;i<=n;i++)
43         scanf("%d",&lst[i]);
44     for(int i=1;i<=m;i++)
45         scanf("%d%d",&t1,&t2),Link(t2,t1);    
46     for(int i=1;i<=n;i++)
47         if(!(deg[i]=mem[i])) hp.push(make_pair(lst[i],i));
48     while(!hp.empty())
49     {
50         pair<int,int> tn=hp.top(); 
51         hp.pop(),stk[++top]=tn.second;
52         for(int i=p[tn.second];i;i=noww[i])
53             if(!(--deg[goal[i]]))
54                 hp.push(make_pair(lst[goal[i]],goal[i]));
55     }
56     while(top) printf("%d ",stk[top--]); puts("");
57     for(int i=1;i<=n;i++) printf("%d ",Solve(i));
58     return 0;
59 }
View Code

 

转载于:https://www.cnblogs.com/ydnhaha/p/10461489.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值