考察:拓扑排序
错误思路1:
先找到字典序最小的拓扑序列,再挨个赋值.
这个思路错在这道题需要的不是字典序最小的序列.而是字典序小的位置尽量靠前的序列.也就是说1 2 3...的位置要尽量考前.序号越小优先级越高
正确思路:
这道题需要保证1 2 3...拓扑序列的位置应该尽量小.也就是说无论他在图里是多么后面.在拓扑序列里也要尽量靠前.要操作图内靠后的元素可以考虑逆向建图.在每次队列里将大元素放在队头,在赋值时再反转.这样序号小的元素就靠前了
1 #include <iostream> 2 #include <queue> 3 #include <algorithm> 4 #include <numeric> 5 using namespace std; 6 const int N = 210;//确定比赛名次那道题是仅仅是字典序最小 7 const int M = 40010;//这道题是要求序号小的位置尽量小 ,因此可能会有以大数在前面为代价. 8 int h[N],e[M],ne[M],d[N],idx,n,m,q[N],ans[N]; 9 void inits() 10 { 11 fill(d,d+N,0); fill(h,h+N,-1); 12 fill(ans,ans+N,0); 13 idx = 0; 14 } 15 void add(int a,int b) 16 { 17 e[idx]=b,ne[idx]=h[a],h[a]=idx++; 18 } 19 void topsort() 20 { 21 int hh=0,tt = -1; 22 for(int i=1;i<=n;i++) if(!d[i]) q[++tt] = i; 23 while(hh<=tt) 24 { 25 sort(q+hh,q+tt+1,greater<int>()); 26 int x = q[hh++]; 27 for(int i=h[x];i!=-1;i=ne[i]) 28 { 29 int j = e[i]; 30 if(--d[j]==0) q[++tt]=j; 31 } 32 } 33 if(tt!=n-1) printf("-1\n"); 34 else{ 35 // for(int i=0;i<n;i++) printf("%d%c",q[i],i==n-1?'\n':' '); 36 reverse(q,q+n); 37 for(int i=0;i<n;i++) ans[q[i]] = i+1; 38 for(int i=1;i<=n;i++) printf("%d%c",ans[i],i==n?'\n':' '); 39 } 40 } 41 int main() 42 { 43 // freopen("in.txt","r",stdin); 44 int t; 45 scanf("%d",&t); 46 while(t--) 47 { 48 scanf("%d%d",&n,&m); 49 inits(); 50 for(int i=1;i<=m;i++){ 51 int x,y; scanf("%d%d",&x,&y); 52 add(y,x); d[x]++; 53 } 54 topsort(); 55 } 56 return 0; 57 }