hdu 2647 Reward(拓扑排序)
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.
译文:蒲公英的叔叔是工厂的老板。随着春节的到来,他想分发奖励给他的工人。现在他在分配奖励方面遇到了麻烦。工人们会比较他们的奖励,有些人可能会要求分配奖励,就像a's奖励超过b's一样.Dandelion的不克不及要满足所有的要求,当然他想用最少的钱。每件作品的奖励将至少为888,因为这是一个幸运数字。
译文:蒲公英的叔叔是工厂的老板。随着春节的到来,他想分发奖励给他的工人。现在他在分配奖励方面遇到了麻烦。工人们会比较他们的奖励,有些人可能会要求分配奖励,就像a's奖励超过b's一样.Dandelion的不克不及要满足所有的要求,当然他想用最少的钱。每件作品的奖励将至少为888,因为这是一个幸运数字。
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.
then m lines ,each line contains two integers a and b ,stands for a's reward should be more than b's.
译文:一行有两个整数n和m,代表作品数量和需求数量(n <= 10000,m <= 20000),
然后是m行,每行包含两个整数a和b,代表a的奖励应该是比b要多。
然后是m行,每行包含两个整数a和b,代表a的奖励应该是比b要多。
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.
译文:对于每一种情况,打印蒲公英的叔叔需要分发的最少钱。如果不能满足所有作品的需求,则打印-1。
Sample Input
2 1
1 2
2 2
1 2
2 1
Sample Output
1777
-1
解题思路:拓扑排序。因为前者奖励比后者多,又要求用最少的钱来发放奖励,所以只取前者比后者多1的奖励金。如果按之前一般思维来做,即将奖金多的指向奖金少的,在拓扑奖金多的这个节点编号时,势必会影响到之前已经拓扑的节点编号的奖励,因为有可能比它奖励还要多1的节点,这样就不好处理之前已经拓扑的节点编号的奖励。因此,这题需要反过来思考,将奖励少的节点编号指向奖励多的节点编号,这样拓扑奖励少的时候,奖励多的只需比奖励少的多1,最终将所有奖励相加再加上888*n即可。题目给出的数据太大,为避免超时,采用邻接表的做法。对于此题的讲解还可以看看这篇博文:hdu 2647 Reward【拓扑排序】
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=10010; 4 vector<int> vec[maxn];//邻接表,每个节点保存与它相连的边的另一个端点 5 queue<int> que; 6 int n,m,u,v,InDeg[maxn],cnt[maxn];//记录每个节点的入度,cnt记录每个节点该得到的奖励 7 bool topsort(){ 8 int num=0; 9 for(int i=1;i<=n;++i)if(!InDeg[i])que.push(i);//预处理,先将入度为0的节点编号入队 10 while(!que.empty()){ 11 int now=que.front();que.pop();num++; 12 for(unsigned int i=0;i<vec[now].size();++i){ 13 if(--InDeg[vec[now][i]]==0)que.push(vec[now][i]); 14 cnt[vec[now][i]]=cnt[now]+1;//只需比出队元素奖励多1即可 15 } 16 } 17 if(num==n)return true;//满足条件的话返回1 18 else return false; 19 } 20 int main() 21 { 22 while(cin>>n>>m){ 23 for(int i=1;i<=n;++i)vec[i].clear();//全部清空 24 memset(InDeg,0,sizeof(InDeg));//全部顶点的度清0 25 memset(cnt,0,sizeof(cnt)); 26 while(m--){ 27 cin>>u>>v; 28 vec[v].push_back(u);//v指向u 29 InDeg[u]++;//u的入度加1 30 } 31 if(topsort()){ 32 int sum=0; 33 for(int i=1;i<=n;++i)sum+=cnt[i]; 34 cout<<(sum+888*n)<<endl; 35 } 36 else cout<<"-1"<<endl; 37 } 38 return 0; 39 }