• HDU2647 Reward 拓扑排序


    Reward

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2075    Accepted Submission(s): 599


    Problem Description
    Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble about how to distribute the rewards.
    The workers will compare their rewards ,and some one may have demands of the distributing of rewards ,just like a's reward should more than b's.Dandelion's unclue wants to fulfill all the demands, of course ,he wants to use the least money.Every work's reward will be at least 888 , because it's a lucky number.
     
    Input
    One line with two integers n and m ,stands for the number of works and the number of demands .(n<=10000,m<=20000)
    then m lines ,each line contains two integers a and b ,stands for a's reward should be more than b's.
     
    Output
    For every case ,print the least money dandelion 's uncle needs to distribute .If it's impossible to fulfill all the works' demands ,print -1.
     
    Sample Input
    2 1 1 2 2 2 1 2 2 1
     
    Sample Output
    1777 -1
     
    /*
    典型的拓扑排序,但是在排序的过程中需要对结点进行分层。
    */
    /*
    //代码一:-----MLE   (网上说的是因为邻接矩阵的原因,占用了太多内存,应该改为邻接表存储)
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define M 20001
    #define N 10001
    int n,m;
    int map[N][N],indegree[N];
    using namespace std;
    
    int toposort()
    {
    	int *queue=new int[n+1];
    	int i,j,k;
    	int sum=0;
    	int temp=888;
    	for(k=0;k<=n;++k)    //控制循环次数,k表示已经排好序的人数
    	{
    		memset(queue,0,(n+1)*sizeof(int));  //记录每层节点的编号
    		int num=0;          //记录每层的节点数
    		for(i=1;i<=n;++i)
    		{
    			if(indegree[i]==-1)   //已经排好序的
    				continue;
    			if(indegree[i]==0)
    			{
    				queue[num++]=i;
    				indegree[i]=-1;
    				++k;
    			}
    		}
    		if(num==0&&k<n)  //表示没有入度为0的节点,说明存在环。
    			return -1;
    		sum+=temp*num;
    		++temp;
    		for(i=0;i<num;++i)      //对应节点的入度减一
    		{
    			for(j=1;j<=n;++j)
    			{
    				if(map[queue[i]][j])
    					--indegree[j];
    			}
    		}
    	}
    	return sum;
    }
    
    int main()
    {
    	while(~scanf("%d%d",&n,&m))
    	{
    		memset(map,0,sizeof(map));
    		memset(indegree,0,sizeof(indegree));
    		for(int i=0;i<m;++i)
    		{
    			int a,b;
    			scanf("%d%d",&a,&b);
    			if(!map[b][a])
    			{
    				++indegree[a];
    				map[b][a]=1;
    			}
    		}
    		printf("%d\n",toposort());
    	}
    	return 0;
    }
    
    */
    //代码二:  ----AC 邻接表存储
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define M 20001
    #define N 10001
    int n,m;
    using namespace std;
    
    struct node
    {
    	int id;
    	node *next;
    }fa[N];
    
    int toposort()
    {
    	int *queue=new int[n+1];
    	node *p;
    	int i,k,num;
    	int sum=0;
    	int temp=888;
    	k=0;			//记录已经排好序的人数
    	while(1)    //控制循环次数,k表示已经排好序的人数
    	{
    		memset(queue,0,(n+1)*sizeof(int));  //记录每层节点的编号
    		num=0;          //记录每层的节点数
    		for(i=1;i<=n;++i)
    		{
    			if(fa[i].id==-1)   //已经排好序的
    				continue;
    			if(fa[i].id==0)
    			{
    				queue[num++]=i;
    				fa[i].id=-1;
    				++k;          
    			}
    		}
    		if(num==0&&k<=n)  //表示没有入度为0的节点,说明存在环。
    			return -1;
    		sum+=temp*num;
    		if(k==n)
    			break;
    		for(i=0;i<num;++i)      //num个节点所连接的边入度都减一
    		{
    			p=fa[queue[i]].next;
    			while(p)
    			{
    				--fa[p->id].id;
    				p=p->next;
    			}
    		}
    		++temp;   //进入下一层之前钱数应加一
    	}
    	return sum;
    }
    
    int main()
    {
    	while(~scanf("%d%d",&n,&m))
    	{
    		for(int i=0;i<=n;++i)
    		{
    			fa[i].id=0;   //用来存储i节点的入读
    			fa[i].next=NULL;
    		}
    		for(i=0;i<m;++i)
    		{
    			int a,b;
    			scanf("%d%d",&a,&b);//反向建边更有助于理解
    			fa[a].id++;
    			node *t=new node;
    			t->id=a;
    			t->next=fa[b].next;
    			fa[b].next=t;
    		}
    		printf("%d\n",toposort());
    	}
    	return 0;
    }
    
    
    //  copy  代码
    /*
    
    */
    

      

    功不成,身已退
  • 相关阅读:
    Git出现error: Your local changes to the following files would be overwritten by merge: ... Please, commit your changes or stash them before you can merge.的问题解决(Git代码冲突)
    JDK内置工具jstack(Java Stack Trace)(转)
    Java 5/Java 6/Java7/Java 8新特性收集
    Linux使用screen实现关闭ssh连接的情况下,让程序继续在后台运行
    Linux出现cannot create temp file for here-document: No space left on device的问题解决
    解决树莓派8G的SD卡只能识别3.3G,SD卡扩容
    Windows下拷贝Linux的文件到本地(Putty)
    Linux下运行Java项目时,出现No X11 DISPLAY variable was set, but this program performed an operation which requires it.的问题解决
    Maven错误 diamond operator is not supported in -source 1.5 (use -source 7 or higher to enable diamond operator)问题解决
    Ubuntu下安装Maven
  • 原文地址:https://www.cnblogs.com/dongsheng/p/2730042.html
Copyright © 2020-2023  润新知