• 【[HNOI2015]菜肴制作】


    (SDSC)讲过的题,复习一下

    如果用一个小根堆来维护拓扑的话显然是会不行的,因为这样求出来的是字典序最小的拓扑序,并不一定是1尽可能在前

    因为字典序是贪心的,如果前面的一位能小就尽可能的小,并不保证1出现尽量靠前

    但是如果建一个反图,求一个反向字典序最大的拓扑序呢

    那么就会有大的数尽量靠前的情况出现,于是交小的数尽量靠后,于是反过来就是小的数尽量靠前了

    于是反着建图+一个大根堆维护就好了

    #include<queue>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define re register
    #define maxn 100005
    struct node
    {
    	int v,nxt;
    }e[maxn<<1];
    int n,m,T;
    int r[maxn],tot,head[maxn],ans[maxn];
    int num=0;
    inline void add_edge(int x,int y)
    {
    	e[++num].v=y;
    	e[num].nxt=head[x];
    	head[x]=num;
    }
    inline int read()
    {
        char c=getchar();
        int x=0;
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9')
          x=(x<<3)+(x<<1)+c-48,c=getchar();
        return x;
    }
    int main()
    {
    	T=read();
    	while(T--)
    	{
    		n=read();
    		m=read();
    		std::priority_queue<int> q;
    		memset(head,0,sizeof(head));
    		num=0;
    		memset(r,0,sizeof(r));
    		int x,y;
    		for(re int i=1;i<=m;i++)
    		{
    			x=read();
    			y=read();
    			r[x]++;
    			add_edge(y,x);
    		}
    		for(re int i=1;i<=n;i++)
    		if(!r[i]) q.push(i),tot++;
    		int t=0;
    		while(!q.empty())
    		{
    			int k=q.top();
    			q.pop();
    			ans[++t]=k;
    			for(re int i=head[k];i;i=e[i].nxt)
    			{
    				r[e[i].v]--;
    				if(!r[e[i].v]) q.push(e[i].v),tot++;
    			}
    		}
    		if(t<n) puts("Impossible!");
    		else 
    		{
    			for(re int i=n;i>=1;i--) printf("%d ",ans[i]);
    			puts("");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    第一次作业
    第五次作业
    第四次作业
    第三次作业
    第二次作业
    第一次作业
    第五次作业
    第四次作业
    第三次作业
    第二次作业
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207809.html
Copyright © 2020-2023  润新知