[HNOI2015]菜肴制作
[HNOI2015]菜肴制作
题意:有n个数排成一列,给定m个限制(x,y),表示x应在y的前面,规定对于x1,x2,x1<x2,每个x1如果不存在一条限制路径(每个限制连一条(x,y)x=>y的边),则x1应排在x2前面,求最终排列
算法:拓扑排序
我们如果单纯的找一个字典序最小的限制队列,这很显然是一个拓扑板子
但是这很显然没有那么简单,你仔细思考会发现,正着搞有很多的后效性,非常难搞
所以,正难则反,我们应该想可不可以反着建图
我们发现,对于最后一位,肯定是没有限制的最大的那个数,然后把对于这个数有限制的数度数减1,以此类推,我们会发现这样非常正确,并没有后效性的影响。
CODE:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define MAXN 100050 using namespace std; struct zlk{ int x; bool operator <(zlk a) const { return x<a.x; } }; priority_queue<zlk> Q; int de[MAXN],n,fir[MAXN],nxt[MAXN],to[MAXN],m,t,tot,q[MAXN],cnt; void ade( int x, int y){ to[++tot]=y; nxt[tot]=fir[x]; fir[x]=tot; } int main(){ cin>>t; while (t--){ tot=0; memset(fir,0, sizeof (fir)); memset(de,0, sizeof (de)); scanf( "%d%d" ,&n,&m); rep(i,1,m){ int x,y; scanf( "%d%d" ,&x,&y); ade(y,x); de[x]++; } rep(i,1,n) if (!de[i]) Q.push((zlk){i}); cnt=0; while (!Q.empty()){ int x=Q.top().x; Q.pop(); q[++cnt]=x; for ( int k=fir[x];k;k=nxt[k]){ de[to[k]]--; if (!de[to[k]]) Q.push((zlk){to[k]}); } } if (cnt!=n){puts( "Impossible!" ); continue ;} while (cnt) cout<<q[cnt--]<< " " ; cout<<endl; } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步