zoukankan      html  css  js  c++  java
  • 【bzoj4010】[HNOI2015]菜肴制作 拓扑排序+堆

    题目描述

    给你一张有向图,问:编号-位置序(即每个编号的位置对应的序列)最小(例如1优先出现在前面,1位置相同的2优先出现在前面,以此类推)的拓扑序是什么?

    输入

    第一行是一个正整数D,表示数据组数。 

    接下来是D组数据。 对于每组数据: 
    第一行两个用空格分开的正整数N和M,分别表示菜肴数目和制作顺序限制的条目数。 
    接下来M行,每行两个正整数x,y,表示“x号菜肴必须先于y号菜肴制作”的限制。(注意:M条限制中可能存在完全相同的限制) 

    输出

    输出文件仅包含 D 行,每行 N 个整数,表示最优的菜肴制作顺序,或者”Impossible!”表示无解(不含引号)。 

    样例输入

    3
    5 4
    5 4
    5 3
    4 2
    3 2
    3 3
    1 2
    2 3
    3 1
    5 2
    5 2
    4 3

    样例输出

    1 5 3 4 2
    Impossible!
    1 5 2 4 3


    题解

    拓扑排序+堆

    正着直接按字典序最小拓扑排序是错的,反例:

    按照题目描述,答案应该为1 5 2 3 4,而正着拓扑排序的答案为1 3 4 5 2

    这里有一个神奇的结论:正的编号-位置序(每个编号的位置对应的序列)等于反的位置-编号序(每个位置的编号对应的序列,即字典序)的逆序。

    换句话说,本题的答案就是把图反过来得到的图的字典序最大的拓扑序的逆序。

    证明:反图的字典序最大,就是尽量的把编号较大的数放在反图遍历序的前面,对应的就在原图的后面,就相当于所有小于这个编号的数向前移动了1个位置。因此,对于某数都是尽量的在它的后面放数。因此尽量的让大数在反图中先遍历,得到的字典序最大拓扑序的逆序就是远答案。

    所以使用堆来维护字典序,进行拓扑排序,倒过来输出即为答案。

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #define N 100010
    using namespace std;
    priority_queue<int> q;
    int head[N] , to[N] , next[N] , cnt , d[N] , ans[N] , tot;
    inline void add(int x , int y)
    {
    	to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt , d[y] ++ ;
    }
    int main()
    {
    	int T;
    	scanf("%d" , &T);
    	while(T -- )
    	{
    		memset(head , 0 , sizeof(head)) , memset(d , 0 , sizeof(d)) , cnt = tot = 0;
    		int n , m , i , x , y;
    		scanf("%d%d" , &n , &m);
    		for(i = 1 ; i <= m ; i ++ ) scanf("%d%d" , &x , &y) , add(y , x);
    		for(i = 1 ; i <= n ; i ++ )
    			if(!d[i])
    				q.push(i);
    		while(!q.empty())
    		{
    			x = q.top() , q.pop() , ans[++tot] = x;
    			for(i = head[x] ; i ; i = next[i])
    			{
    				d[to[i]] -- ;
    				if(!d[to[i]]) q.push(to[i]);
    			}
    		}
    		if(tot == n)
    			for(i = n ; i ; i -- )
    				printf("%d " , ans[i]);
    		else printf("Impossible!");
    		printf("
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    nullnullUVa 10066 The Twin Towers(LCS水题)
    代码错误zoj1298Domino Effect
    实现图形Qt学习:三维绘图之OpenGL和Qt的结合
    情况数组zoj2412Farm Irrigation
    nullnulle人事管理系统人事档案变更管理人员合同变更
    判断条件UVa 10192 Vacation(LCS水题)
    查询数量查看表的所有相关列信息
    代码提交省赛啊省赛
    输入声音如何搜索一张发音的图片
    数组字符串uva 10405 Longest Common Subsequence(最长公共子序列)
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7510058.html
Copyright © 2011-2022 走看看