cogs1958 菜肴制作 拓扑排序
链接:http://cogs.pro/cogs/problem/problem.php?pid=1958
题意:给出一些约束条件,要求得出字典序最小的符合所有条件的方案。
这道题很显然是一个在$AOE$上的程序流程问题,显然是一个拓扑排序。但是这个拓扑排序有点意思,因为它要求字典序最小。
那么我们就要找出一种方法,使得最小的出现在最前面,那么我们就考虑用堆维护,倒序建边。
如果我们正序建边,很有可能我们选取了一个点之后再向下走发现了一个更小的点,而且这个更小的点还是可以放在前面的。而如果倒序建边,小的就一定会后出现,出现时大的已经出现过。那么我们就用栈来表示,可以确定这一方案是最优的。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<queue> 5 #include<stack> 6 #include<iostream> 7 #include<cstring> 8 using namespace std; 9 const int maxn=100005; 10 template<class T> 11 void clear(T &x) 12 { 13 T tmp;swap(x,tmp); 14 } 15 struct node 16 { 17 int from,to,next; 18 }edge[maxn]; 19 int head[maxn],tot; 20 void addedge(int u,int v) 21 { 22 edge[++tot]=(node){u,v,head[u]};head[u]=tot; 23 } 24 priority_queue<int>q; 25 stack<int>s; 26 int n,m; 27 int entrance_degree[maxn]; 28 int haha() 29 { 30 freopen("dishes.in","r",stdin); 31 freopen("dishes.out","w",stdout); 32 int t;scanf("%d",&t); 33 while(t--) 34 { 35 memset(entrance_degree,0,sizeof(entrance_degree)); 36 memset(head,0,sizeof(head));clear(s);tot=0; 37 scanf("%d%d",&n,&m); 38 for(int i=1;i<=m;i++) 39 { 40 int x,y;scanf("%d%d",&x,&y); 41 addedge(y,x);entrance_degree[x]++; 42 } 43 int cnt=0; 44 for(int i=1;i<=n;i++) 45 if(!entrance_degree[i])q.push(i); 46 while(!q.empty()) 47 { 48 int l=q.top();q.pop(); 49 s.push(l);cnt++; 50 for(int i=head[l];i;i=edge[ i].next) 51 { 52 int v=edge[i].to; 53 entrance_degree[v]--; 54 if(!entrance_degree[v])q.push(v); 55 } 56 } 57 if(cnt!=n)puts("Impossible!"); 58 else 59 { 60 while(!s.empty()) 61 { 62 printf("%d ",s.top()); 63 s.pop(); 64 } 65 puts(""); 66 } 67 } 68 } 69 int sb=haha(); 70 int main(){;}
只要是活着的东西,就算是神我也杀给你看。