Reward (拓扑排序)

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. InputOne 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. OutputFor 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

题意:

老板要给N个员工发工资,要求每个人最少888块且要满足M个要求.比如1号员工的工资要比2号员工的工资多.老板准备满足所有要求且最终发的奖金总数要最少.如果可行输出总数,不可行输出-1.

思路:

其实就是可以转换为一个有向边的图,然后问是否可进行拓扑排序,注意一点就是要加入一个层次,每一层都要加一,一开始想的是直接888*n然后再加上点的个数的累加,其实这样想是错误的,因为有可能有不同的点位于同一个层次上面,具体就是将整个拓扑图分层,位于第0层的是那些可以获得888奖金的,位于第1层的是可以获得889奖金的,依次类推.最终的奖金总数就是888*N+(所有节点层数总和).所以,综上所述,我们依然用的拓扑排序的方法,不过我们分解图的过程中只需要计算出每个节点所在的树层次即可.

代码:

#include<cstdio>  
#include<cstring>  
#include<vector>  
#include<queue>  
#define maxn 10000+10
using namespace std;
int n,m;
int ans;
struct Node{  //因为每个点有多个变量,这个点的入度,层次,以及相临边,所以用结构体表示较为方便
	int in,dep;
	int head;//head为0时表示的无边
}node[maxn];
struct Edge{  //邻接表
	int to; //尾结点
	int next; //xiayitiaobian
}edge[20000+10];

void add(int i,int u,int v){  //加一条由有u->v的路
	edge[i].next=node[u].head;
	edge[i].to=v;
	node[u].head=i;
	node[v].in++;
}

bool topo(){
	queue<int>Q;
	int sum=0;
	ans=0;
	for(int i=1;i<=n;i++) if(node[i].in==0)
	Q.push(i);
	while(!Q.empty()){
		int u=Q.front();
		Q.pop();
		sum++;
		ans+=node[u].dep;
		for(int e=node[u].head;e;e=edge[e].next){
			int v=edge[e].to;
			if(--node[v].in==0){
				Q.push(v);
				node[v].dep=node[u].dep+1;
			}
		} 
	}
	return sum==n;
}

int main()
{
	while(scanf("%d%d",&n,&m)==2){
		memset(node,0,sizeof(node));
		for(int i=1;i<=m;i++){
			int u,v;
			scanf("%d%d",&u,&v);
			add(i,v,u);
		}
		printf("%d\n",topo()?888*n+ans:-1);
	}
	return 0;
}

地址:点击打开链接

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/sinat_37668729/article/details/79175207
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞