1. 程式人生 > >題解報告:hdu 2647 Reward(拓撲排序)

題解報告:hdu 2647 Reward(拓撲排序)

一個 may lan 應該 遇到 net acm http nes

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2647

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,因為這是一個幸運數字。
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. 譯文:一行有兩個整數n和m,代表作品數量和需求數量(n <= 10000,m <= 20000),

然後是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 }

題解報告:hdu 2647 Reward(拓撲排序)