逆拓扑排序 Reward HDU - 2647

Reward

 HDU - 2647 

题意:每个人的起始金额是888,有些人觉得自己做的比另一个人好所以应该多得一些钱,问最少需要花多少钱,如果不能满足所有员工的要求,输出 -1

样例1:

2 1

1 2 输出1777

1认为自己的报酬应该比2多,所以2为888,1为889是最小的情况

样例2:

5 4

1 2 2 5 2 4 4 3 输出4446

相当于给定一张图,n个节点,m条边,问你是否存在环,若存在,则输出-1,否则如下面思路所示

思路:可以把整张图反过来,若存在u->v,则实际上连接v->u,v的入度为0,那么我们就可以保证初始入度为0的点金额一定是888,在队列过程中,后面的点都继承前面的金额并+1,

#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
typedef long long ll; 
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
/*------------------------------------------------------------------------*/
const int maxn=1e4+10; 
vector<int>G[maxn];
int du[maxn];
int n,m;
queue<int>q;
int ans[maxn];
void init(){
	for(int i=1;i<=n;++i){
		G[i].clear();
		du[i]=0;
		ans[i]=0;
	}
	while(!q.empty())q.pop();
	
}
int main( )
{	
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    //freopen("a.txt","r",stdin);
    //freopen("a.txt","w",stdout);
    
    //cin>>n>>m;
    
    while(cin>>n>>m){
    	
    	init();
    	for(int i=1;i<=m;++i){
	    	int u,v;
	    	cin>>u>>v;
	    	
	    	G[v].push_back(u);
	    	du[u]++;
	    }
	    
	    for(int i=1;i<=n;++i)if(!du[i])q.push(i);//度为0入队
		
		while(!q.empty()){
			
			int now=q.front();q.pop();
			//ans[]
			for(int i=0;i<G[now].size();++i){
				int temp=G[now][i];
				du[temp]--;
				ans[temp]=max(ans[now]+1,ans[temp]);
				if(du[temp]==0)
				q.push(temp);
			}
		}
		int flag=0;
		for(int i=1;i<=n;++i){
			if(du[i])
			flag=1;
			break;
		}
		
		if(!flag){
			int res=n*888;
			for(int i=1;i<=n;++i)res+=ans[i];
			cout<<res<<endl;
		}//cout<<(n*888+n-1)<<endl;
		else cout<<-1<<endl;
    }
	
	
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值