• [HNOI2015]菜肴制作


    洛咕

    题意:给定(m)个有序对((a,b)),构造一个(n)的排列,满足(m)个有序对中(a)均排在(b)的前面,且1尽量靠前,在1尽量靠前的前提下,2尽量靠前,....以此类推.(n,m<=100000.)

    分析:结论题???还是不会证结论的那种.

    首先一个合法的排列就是反向图的拓扑序,然后是要让(1,2...)尽量靠前,那么就是反向图的拓扑序的字典序尽量大,这个我们直接开一个大根堆维护点的编号就好了.

    具体说来,反向建图,然后把度数为0的点丢进大根堆里跑拓扑排序即可.如果跑完拓扑之后的排列里面没有n个数,判断无解,否则倒序输出就是答案了.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=100005;
    int deg[N],Ans[N];
    int tot,head[N],nxt[N],to[N];
    priority_queue<int>q;
    inline void add(int a,int b){
    	nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
    }
    int main(){
    	int T=read();
    	while(T--){
    		tot=0;memset(head,0,sizeof(head));
    		memset(deg,0,sizeof(deg));
    		int n=read(),m=read();
    		for(int i=1;i<=m;++i){
    			int a=read(),b=read();
    			add(b,a);++deg[a];
    		}
    		for(int i=1;i<=n;++i)if(!deg[i])q.push(i);
    		int ans=0;
    		while(q.size()){
    			int u=q.top();q.pop();
    			Ans[++ans]=u;
    			for(int i=head[u];i;i=nxt[i]){
    				int v=to[i];--deg[v];
    				if(!deg[v])q.push(v);
    			}
    		}
    		if(ans!=n)puts("Impossible!");
    		else{
    			for(int i=ans;i>=1;--i)
    				printf("%d ",Ans[i]);
    			printf("
    ");
    		}
    	}
        return 0;
    }
    
    
  • 相关阅读:
    如何让两个线程同时运行
    测试人员绩效评价方法
    转载:浅谈实施软件测试风险分析
    项目测试流程总结
    HttpClient使用小结
    浅谈分布式事务原理及其应用场景
    (.NET高级课程笔记)Lambd、Linq总结
    (.NET高级课程笔记)反射总结
    (.NET高级课程笔记)泛型总结
    Lambda表达式详解(例子详解)(转自:http://blog.csdn.net/damon316/article/details/51734661)
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11543854.html
Copyright © 2020-2023  润新知