洛谷 P1954 [NOI2010]航空管制

https://www.luogu.org/problemnew/show/P1954

拓扑排序,

注意到如果正着建图("a出现早于b"=>"a向b连边"),贪心选择,可能前面某一次的选择造成后面找不出合法方案;

但是如果反过来建图,而且每一次选择当前入度为0的点中K值最大的,那么一定不会产生前面那种情况;因此用堆维护

对于第一问,直接跑一遍即可。。(而且题面还说了一定有可行解)

对于第二问,

设当前要使得now的起飞序号最小,那么就是使得在反着的图的拓扑序遍历中,now被遍历的次序尽量往后排

那么,在遍历到now时,不减小其出边指向的点的入度;不改变拓扑排序的其他流程

这样,如果什么时候堆为空了,或者堆中弹出来的那个节点已经不满足时间限制了,说明这时必须遍历now了

洛谷卡常。。。

手工定义一个pii比pair<int,int>要快200ms+。。不知道为什么(看stl源码,pair<int,int>的逻辑也是很简单的)

  1 #pragma GCC optimize(3)
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #include<queue>
  7 using namespace std;
  8 #define fi first
  9 #define se second
 10 #define pb push_back
 11 typedef long long ll;
 12 typedef unsigned long long ull;
 13 struct pii
 14 {
 15     int fi,se;
 16     pii(){}
 17     pii(int a,int b):fi(a),se(b){}
 18 };
 19 bool operator<(const pii &a,const pii &b)
 20 {
 21     return a.fi<b.fi||(a.fi==b.fi&&a.se<b.se);
 22 }
 23 struct E
 24 {
 25     int to,nxt;
 26 }e[10010];
 27 int f1[2010],ne;
 28 int n,m,K[2010];
 29 int inn[2010],in[2010],num;
 30 vector<int> ans;
 31 struct
 32 {
 33     pii d[2010];
 34     int tp;
 35     void clear(){tp=0;}
 36     void push(const pii &x)
 37     {
 38         d[tp++]=x;
 39         push_heap(d,d+tp);
 40     }
 41     void pop()    {pop_heap(d,d+tp);--tp;}
 42     pii top()    {return d[0];}
 43     bool empty(){return tp==0;}
 44 }q;
 45 template<class T>
 46 inline void read(T &x) {
 47     int f=1;x=0;char ch=getchar();
 48     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
 49     while(ch>='0'&&ch<='9'){x*=10;x+=(ch-'0');ch=getchar();}
 50     x*=f;
 51 }
 52 template<class T>
 53 inline void write(T x) {
 54     if(x<0) putchar('-'),x=-x;
 55     if(x>9) write(x/10);
 56     putchar(x%10+'0');
 57 }
 58 int main()
 59 {
 60     int i,a,b,u,k;pii t;
 61     read(n);read(m);
 62     for(i=1;i<=n;i++)    read(K[i]);
 63     for(i=1;i<=m;i++)
 64     {
 65         read(a);read(b);
 66         e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;
 67         inn[a]++;
 68     }
 69     {
 70         memcpy(in+1,inn+1,sizeof(int)*n);
 71         for(i=1;i<=n;i++)
 72             if(!in[i])
 73                 q.push(pii(K[i],i));
 74         while(!q.empty())
 75         {
 76             t=q.top();q.pop();
 77             u=t.se;
 78             ans.pb(u);
 79             for(k=f1[u];k;k=e[k].nxt)
 80             {
 81                 in[e[k].to]--;
 82                 if(!in[e[k].to])
 83                     q.push(pii(K[e[k].to],e[k].to));
 84             }
 85         }
 86         for(i=ans.size()-1;i>=0;i--)
 87             write(ans[i]),putchar(' ');
 88         puts("");
 89     }
 90     for(int now=1;now<=n;now++)
 91     {
 92         q.clear();
 93         num=0;
 94         memcpy(in+1,inn+1,sizeof(int)*n);
 95         for(i=1;i<=n;i++)
 96             if(!in[i])
 97                 q.push(pii(K[i],i));
 98         while(!q.empty())
 99         {
100             t=q.top();q.pop();
101             u=t.se;
102             if(n-num>K[u])    break;
103             if(u==now)    continue;
104             num++;
105             for(k=f1[u];k;k=e[k].nxt)
106             {
107                 in[e[k].to]--;
108                 if(!in[e[k].to])
109                     q.push(pii(K[e[k].to],e[k].to));
110             }
111         }
112         write(n-num);putchar(' ');
113     }
114     return 0;
115 }

 

posted @ 2018-08-02 21:16  hehe_54321  阅读(242)  评论(0编辑  收藏  举报
AmazingCounters.com