题解 P3243 【[HNOI2015]菜肴制作】
这道题看起来就是个裸的拓扑排序,抄上模板就能AC。
上面这种想法一看就不现实,然鹅我第一次还真就这么写了,然后被随意hack。
我们需要注意一句话:
现在,酒店希望能求出一个最优的菜肴的制作顺序,使得小 A能尽量先吃到质量高的菜肴:
这句话什么意思呢?
看上去它是说想要一个字典序最小的排列,但我们可以发现,题目并不是强求质量高一定先,而是有一个宽限范围(可能我讲的比较玄学)。
解决方案是贪心地把大的放在末尾,那么最后一定是最优解。
所以我们跑一个字典序最大的拓扑就可以了。
字典序最大就是反着跑一遍字典序最小。
AC代码如下:
820ms 133668kb
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 namespace StandardIO { 6 7 template<typename T>inline void read (T &x) { 8 x=0;T f=1;char c=getchar(); 9 for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1; 10 for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0'; 11 x*=f; 12 } 13 14 template<typename T>inline void write (T x) { 15 if (x<0) putchar('-'),x*=-1; 16 if (x>=10) write(x/10); 17 putchar(x%10+'0'); 18 } 19 20 } 21 22 using namespace StandardIO; 23 24 namespace Solve { 25 26 const int N=300300; 27 28 int T,n,m,cnt; 29 int indeg[N],ans[N]; 30 vector<int>graph[N]; 31 32 inline void toposort () { 33 int temp[N]; 34 priority_queue<int>q; 35 memcpy(temp,indeg,sizeof(indeg)); 36 while(!q.empty())q.pop(); 37 for (register int i=1; i<=n; ++i) { 38 if (temp[i]==0) q.push(i); 39 } 40 while (!q.empty()) { 41 int v=q.top();q.pop(); 42 ans[++cnt]=v; 43 for (register int i=0; i<graph[v].size(); ++i) { 44 int to=graph[v][i]; 45 temp[to]--; 46 if (temp[to]==0) q.push(to); 47 } 48 } 49 } 50 51 inline void solve () { 52 read(T); 53 while (T--) { 54 read(n),read(m); 55 cnt=0,memset(indeg,0,sizeof(indeg)); 56 for (register int i=1; i<=n; ++i) { 57 graph[i].clear(); 58 } 59 for (register int i=1; i<=m; ++i) { 60 int x,y; 61 read(x),read(y); 62 indeg[x]++; 63 graph[y].push_back(x); 64 } 65 toposort(); 66 if (cnt!=n) puts("Impossible!"); 67 else { 68 for (register int i=n; i>=1; --i) write(ans[i]),putchar(' '); 69 putchar('\n'); 70 } 71 } 72 73 } 74 } 75 76 using namespace Solve; 77 78 int main () { 79 // freopen(".in","r",stdin); 80 // freopen(".out","w",stdout); 81 solve(); 82 }