Reward HDU-2647 (拓扑排序 判断成环+反向存图+等级记录)

面对复杂的员工奖金需求,本文探讨了一种基于拓扑排序的高效奖金分配算法,确保满足所有条件的同时,实现最少资金使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击去杭电AC 一起拿奖金

先看题目:

Reward

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

 

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

  • 要过年了,老板大气,要发年终奖了,每人888+
  • 然鹅年终奖也是有等级的,并不是所有的人能都拿到一样奖金,这就要给大家排个序,而排序的方法就是拓扑排序
  • 刚开始还以为是个线性关系,后来发现并不是,存在那种某个等级上蹲着好几个人的那种情况。。。

但这题是个坑,他给你的关系是a>b,通常情况下拓扑排序都是按大于关系来建图,但是关于这道题谁也不知道最高的等级是多少,所以只能逆向思维,根据小于关系来反向建图

还有个坑就是这道题的数据 1e4+,开个二维数组还真就爆内存了。。。深受其害~_~

可以用vector(然鹅我并不会)就只能先用静态链表了,vector的写法我一定会补上来的  ヾ(◍°∇°◍)ノ゙

 

 还有就是代码的问题,一不小心把 j 写成 了,调了半天没找到哪里的错。。。太卑微了  Orz

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int mm=50005;

int n,m;
int head[mm];
int cnt;
int ru[mm];
int ceng[mm];//记录每一层的数量 

struct node{
	int to;//pp[i].to表示 路径i->to  
	int next;
}pp[mm*2];

int add(int x,int y){
	for(int i=head[x];i!=-1;i=pp[i].next)
		if(pp[i].to==y)
			return 0;//去重边 
			
	pp[cnt].to=y;
	pp[cnt].next=head[x];
	head[x]=cnt++;
	return 1; 
}

void topo(){
	queue<int>q;
	int sum=0;
	int num=0;
	for(int i=1;i<=n;i++){
		if(ru[i]==0)
			q.push(i);
	}
	while(!q.empty()){
		int size=q.size();
		ceng[sum++]=size;//每一层的数量  
		for(int i=0;i<size;i++){
			int temp=q.front();
			q.pop();
			num++;//判断是否成环 
			for(int j=head[temp];j!=-1;j=pp[j].next){
				ru[pp[j].to]--;
				if(ru[pp[j].to]==0)
					q.push(pp[j].to); //憨瓜,把 j写成 i了。。。 
			}
		}
	}
	if(num==n){
		int res=0;
		for(int i=0;i<sum;i++)
			res+=(888+i)*ceng[i];//每一层的钱 
		printf("%d\n",res); 
	} 
	else printf("-1\n");
}

int main()
{
	while(scanf("%d%d",&n,&m)!=EOF){
		cnt=0;
		memset(ru,0,sizeof(ru));
		memset(head,-1,sizeof(ru));
		int x,y;
		while(m--){
			cin>>x>>y;
			if(add(y,x)==1)	//反向存图!!! 
				ru[x]++;	//	
		}
		topo();
	}
	return 0;
 } 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值