HDU 2647Reward

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2647

Sample Input
2 1
1 2
2 2
1 2
2 1
Sample Output
1777
-1

题意:老板要发工资,但一些员工有自己的小算盘,并向老板提了出来,员工a和b,a的工资要比b的工资高。老板想尽量满足员工的要求,并且使自己支付的总金额最少。每个人的最低工资为888。(这老板可真是够扣的,建议员工集体罢工)

解题思路:首先老板想要满足提出要求的员工的要求(因为有些员工并没有要求(这样的员工老板最喜欢了))。老板要满足所有要求就要保证这些要求不冲突,如果要求不冲突,这像极了拓扑排序(离散中有)中的不成环。如果成环,则说明要求冲突,不成环则说明不冲突。不了解拓扑排序的不要紧,看看代码就明白了。

Code:

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>

using namespace std;
const int maxn = 20005;
int n,m,in[maxn],a[maxn];
vector<int>v[maxn];

int main(){
	while(cin>>n>>m){
		int sum=0;
		memset(in,0,sizeof(in));
		memset(a,0,sizeof(a));//
		for(int i=1;i<=n;i++) a[i]=888;// 使每个员工的初始工资为888 
		sum=888*n;//
		for(int i=1;i<=n;i++) v[i].clear();
		for(int i=1;i<=m;i++){
			int x,y;
			cin>>x>>y;
			in[x]++; 
			v[y].push_back(x);//构图 
		}
		queue<int>q;
		for(int i=1;i<=n;i++){
			if(in[i]==0){
				q.push(i);//将入度为0的点入队 
			}
		}
		while(!q.empty()){
			int xx = q.front();
			q.pop();
			n--;//将入度为0的点剔除,如果不成环,最后n==0 
			for(int i=0;i<v[xx].size();i++){
				int yy = v[xx][i];//
				if(a[xx]>=a[yy]){//满足每个员工的要求 
					int temp=a[yy];//
					a[yy]=a[xx]+1;//
					sum+=(a[yy]-temp);//
				}//除去这些画了双杠的行,其他的基本就是拓扑排序的模板 
				in[v[xx][i]]--;//删边 
				if(in[v[xx][i]]==0){
					q.push(v[xx][i]);
				}
			}
		}
		//cout<<n<<endl;
		if(n) cout<<"-1\n";
		else cout<<sum<<endl;
	}
	
	return 0;
}
posted @ 2019-08-07 15:30  voids5  阅读(66)  评论(0编辑  收藏  举报