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 }