题目要求要求在满足约束条件的情况下,使小的序号尽力靠前。
坑点就在这里。小的序号尽量靠前并非代表字典序,它要求多种情况时,先使1靠前(可能1仅仅能在第2或第3位 那么就要使它在第2位),其次2,3。
。而不是在当前情况下,该位最小是哪个就输出哪个
所以直接拓扑排序。或者优先队列都是错的。由于这样都仅仅能保证字典序最小。能够參考代码后面的例子理解
正确做法应该是 反向建图后,用最大值优先的优先队列来拓扑排序,这样能保证在可能的情况下,先选最大的,把最小的留到最后选。
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<queue> const int maxn=30010; using namespace std; vector<int> e[maxn]; int n,m,in[maxn],ans[maxn],cnt; struct cmp { bool operator ()(int &a,int &b){ return a<b;//最大值优先 } }; void topo() { priority_queue<int,vector<int>,cmp> q; for(int i=1;i<=n;i++) if(in[i]==0) q.push(i); int flag=0; int x,i; while(!q.empty()) { x=q.top(); q.pop(); ans[++cnt]=x; for(i=0;i<e[x].size();i++) { in[e[x][i]]--; if(in[e[x][i]]==0) q.push(e[x][i]); } } } int main() { int t,a,b,i; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=0;i<=n;i++) e[i].clear(); memset(in,0,sizeof in); while(m--) { scanf("%d%d",&a,&b); e[b].push_back(a); in[a]++; } cnt=0; topo(); printf("%d",ans[cnt]); for(i=cnt-1;i>0;i--) printf(" %d",ans[i]); puts(""); } return 0; } /* 4 2 3 2 4 1 应该输出4132 */