[bzoj4010]菜肴制作
大意是让你找到一个拓扑序然后保证第i个数尽量靠前。
显然每次都选最小的点是不成立的(样例都过不了)
然而我们可以考虑建反图,然后这个拓扑序反过来就是原图的一个拓扑序。
发现题意就是让你尽量使反过来的拓扑序字典序尽量大。
我们在反图上跑toposort,同时把队列换成优先队列,优先弹出权值大的点,就是答案了。
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,M=2e5+5;
priority_queue<int>Q;
int hed[N],to[M],nxt[M],d[N],cnt;
inline void adde(int u,int v){
cnt++;to[cnt]=v,nxt[cnt]=hed[u];hed[u]=cnt;
}
int topo[N],num;
int n,m;
int main()
{
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
cnt=0;
for(int i=1;i<=n;i++)d[i]=hed[i]=0;
for(int i=1;i<=m;i++){
int u,v;scanf("%d%d",&u,&v);
d[u]++,adde(v,u);
}
for(int i=1;i<=n;i++){
if(!d[i])Q.push(i);
}
num=0;
while(!Q.empty()){
int u=Q.top();Q.pop();
topo[++num]=u;
for(int i=hed[u];i;i=nxt[i]){
int v=to[i];d[v]--;
if(!d[v])Q.push(v);
}
}
if(num<n)printf("Impossible!");
else for(int i=num;i;i--)printf("%d ",topo[i]);
printf("\n");
}
}