洛谷 P3243 [HNOI2015]菜肴制作 题解

每日一题 day60 打卡

Analysis

这道题一看就感觉是个拓扑排序,但因为按字典序最小的排序会有问题(见第三个样例)主要原因是每次选择有后效性,而从后往前就不会存在这个问题,因为每个子任务都是一个点。

于是就是一个裸的拓扑排序了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define int long long
#define maxn 100000+10
#define rep(i,s,e) for(register int i=s;i<=e;++i)
#define dwn(i,s,e) for(register int i=s;i>=e;--i)
using namespace std;
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
    return f*x;
}
inline void write(int x)
{
    if(x<0) {putchar('-'); x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int T;
int n,m,cnt,num;
int head[maxn],ans[maxn];
int degree[maxn],book[maxn];
struct node
{
    int v,nex;
}edge[maxn];
priority_queue<int> q;
inline void add(int x,int y)
{
    edge[++cnt].v=y;
    edge[cnt].nex=head[x];
    head[x]=cnt;
}
signed main()
{
    T=read();
    while(T--)
    {
        cnt=0;
        num=0;
        memset(head,0,sizeof(head));
        memset(degree,0,sizeof(degree));
        n=read();m=read();
        rep(i,1,m)
        {
            int x=read(),y=read();
            add(y,x);
            degree[x]++;
        }
        rep(i,1,n) 
            if(degree[i]==0) q.push(i);
        while(!q.empty())
        {
            int top=q.top();
            q.pop();
            ans[++num]=top;
            for(int i=head[top];i;i=edge[i].nex)
            {
                int to=edge[i].v;
                --degree[to];
                if(degree[to]==0) q.push(to);
            }
        }
        if(num<n) {printf("Impossible!
"); continue;}
        dwn(i,n,1) {write(ans[i]); putchar(' ');}
        printf("
");
    }
    return 0;
}

请各位大佬斧正(反正我不认识斧正是什么意思)

原文地址:https://www.cnblogs.com/handsome-zyc/p/12039927.html