题目链接:http://codeforces.com/problemset/problem/825/E
题意:给一个有向图,求一个排列,这个排列是每一个点的序号,使得序号对应的点的排序符合拓扑序并且这个排列字典序最小。
直接跑字典序最小的拓扑排序是不行的,因为那样只是确保点的字典序而非这个排列的字典序,比如这个数据:
10 1
5 2
反过来考虑,点号大的入度为0的点一定排在后面,这个位置确定了。但是点好小的入度为0的未必一定排在前面,因为这个点之前可能有入度不为0,但是与此点无关的点在前面,按题意这种点是要比当前点的序号小的。
反向建图,跑字典序最大的拓扑排序就行了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 100100; 5 int n, m, cnt; 6 vector<int> G[maxn]; 7 int ret[maxn], in[maxn]; 8 priority_queue<int> pq; 9 10 void init() { 11 cnt = n; 12 memset(in, 0, sizeof(in)); 13 while(!pq.empty()) pq.pop(); 14 for(int i = 0; i < maxn; i++) G[i].clear(); 15 } 16 17 signed main() { 18 // freopen("in", "r", stdin); 19 int u, v; 20 while(~scanf("%d%d",&n,&m)) { 21 init(); 22 for(int i = 0; i < m; i++) { 23 scanf("%d%d",&u,&v); 24 G[v].push_back(u); 25 in[u]++; 26 } 27 for(int i = 1; i <= n; i++) { 28 if(!in[i]) pq.push(i); 29 } 30 while(!pq.empty()) { 31 int u = pq.top(); pq.pop(); 32 ret[u] = cnt--; 33 for(auto v : G[u]) { 34 in[v]--; 35 if(in[v] == 0) pq.push(v); 36 } 37 } 38 for(int i = 1; i <= n; i++) { 39 printf("%d%c", ret[i], i==n?'\n':' '); 40 } 41 } 42 return 0; 43 }