正常的字典序最小拓扑序是用pq正着做就行的
但是这个他不是求字典序最小的拓扑序,而是对每个点赋一个权值(权值为一个排列),使得权值大小满足拓扑序的关系,且最小化权值序列的字典序
这个东西是不能正着贪的,有一个简单的反例是n=4,m=2,4->1,3->2
因为这个东西对应的不是使权值小的编号尽可能小,而是编号小的权值尽可能小(这样才满足字典序最小)
这个倒着做拓扑排序,每次拿出编号最大的可行的,按这个顺序从大往小填入权值
复杂度(O(n log n))
1 #include<bits/stdc++.h> 2 #define maxn 100005 3 using namespace std; 4 int n,m; 5 vector<int> g[maxn]; 6 int ind[maxn],Ans[maxn]; 7 int main() 8 { 9 scanf("%d%d",&n,&m); 10 for(int u,v,i=1;i<=m;++i) 11 { 12 scanf("%d%d",&u,&v); 13 g[v].push_back(u); 14 ind[u]++; 15 } 16 priority_queue<int> q; 17 for(int i=1;i<=n;++i)if(!ind[i])q.push(i); 18 int id=n; 19 while(!q.empty()) 20 { 21 int u=q.top();q.pop(); 22 Ans[u]=id--; 23 for(int v:g[u]) 24 { 25 ind[v]--; 26 if(!ind[v])q.push(v); 27 } 28 } 29 for(int i=1;i<=n;++i)printf("%d ",Ans[i]); 30 }