首页 > 其他 > 详细

P3243 [HNOI2015]菜肴制作

时间:2019-12-21 19:22:56      阅读:89      评论:0      收藏:0      [点我收藏+]

题意

这题上来很容易想去求最小的拓扑序,即将队列换成堆的做法。

然而题目要求小的数尽量靠前,我们就拿样例的第三个说:

字典序最小:\(14352\)

正解:\(15243\)

因为正解中\(2\)比字典序最小拓扑序的更靠前(\(3<5\))。

也就说越小的数越应该在前面,之后再考虑其他的数,那么正着不好想不妨反过来:越大的数越应该靠后。

于是建反图求字典序最大的拓朴序,之后反着输出即可。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
struct edge
{
    int to,nxt;
}e[maxn];
int T,n,m,cnt,tot;
int head[maxn],deg[maxn],a[maxn];
inline void add(int u,int v)
{
    e[++cnt].nxt=head[u];
    head[u]=cnt;
    e[cnt].to=v;deg[v]++;
}
void init()
{
    memset(head,0,sizeof(head));
    memset(deg,0,sizeof(deg));
    cnt=tot=0;
}
void topsort()
{
    priority_queue<int> q;
    for(int i=1;i<=n;i++) if(!deg[i]) q.push(i);
    while(!q.empty())
    {
        int x=q.top();q.pop();a[++tot]=x;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;deg[y]--;
            if(!deg[y]) q.push(y);
        }
    }
    if(tot<n) printf("Impossible!");
    else for(int i=tot;i;i--) printf("%d ",a[i]);
    puts("");
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++) 
        {
            int u,v;scanf("%d%d",&u,&v);
            add(v,u);
        }
        topsort();
    }
    return 0;
}

P3243 [HNOI2015]菜肴制作

原文:https://www.cnblogs.com/nofind/p/12077777.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!