HDU ACM 2647 Reward (topology----拓扑排序)
http://acm.hdu.edu.cn/showproblem.php?pid=2647
题意:老板想要用最少的钱给所有人发奖金,每个人最少888元,但由于有人的奖金有比别人多,要求求出最少的奖金.
输入:第一行两个数字n,m m表示人数 m表示接下有m行输入.
输入m组 a b 表示a的奖金要比b的多.
输出:输出最少的奖金数.
如果不可能求出,输出-1
用的书拓扑排序.
由于要用最少的钱的完成.所以不能直接用拓扑排序一找到入度为0的点,必须进行一些变形.
否则会出现错误.
在遍历每个点时,先找到1,1的奖金为888.正确
接下来遍历时,遍历到2,无法判断2应该发多少钱.
用了两种方法做.两种方法都是topper排序的变形,且用vector存储数据.
方法一:做第每趟搜索时,找到入度为0的点时不直接删除与该点,而是先找出所有入度为0的点,用队列记录
最后再出队,删除该点.
//View Code
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <queue> 5 using namespace std; 6 const int MAX = 10000 + 10; 7 int in_degree[MAX]; 8 bool used[MAX]; 9 int sum; 10 int used_num; 11 queue <int> q; 12 void find_zero(int n,int now) 13 { 14 int i; 15 for(i=1;i<=n;i++) 16 { 17 if(!used[i] && in_degree[i] == 0) 18 { 19 used[i] = 1; 20 q.push(i); 21 sum = sum + now + 888; 22 used_num++; 23 } 24 } 25 return ; 26 } 27 int main() 28 { 29 int n,m; 30 while(cin>>n>>m) 31 { 32 int i,j; 33 vector <int> v[MAX]; 34 while(!q.empty()) 35 { 36 q.pop (); 37 } 38 sum = 0; 39 used_num=0; 40 memset(used,0,sizeof(used)); 41 memset(in_degree,0,sizeof(in_degree)); 42 int max1 = -1; 43 for(i=1;i<=m;i++) 44 { 45 int a,b; 46 cin>>a>>b; 47 v[b].push_back(a); 48 in_degree[a]++; 49 } 50 int y_n = 1; 51 i=0; 52 while(used_num < n) 53 { 54 i++; 55 find_zero(n,i-1); 56 if(q.empty() && used_num < n) 57 { 58 y_n = 0; 59 break; 60 } 61 else 62 { 63 while(!q.empty()) 64 { 65 int mark = q.front (); 66 q.pop(); 67 for(j=0;j<v[mark].size();j++) 68 { 69 in_degree[v[mark][j]]--; 70 } 71 } 72 } 73 } 74 if(y_n == 0) 75 { 76 cout<<"-1"<<endl; 77 } 78 else 79 { 80 cout<<sum<<endl; 81 } 82 } 83 return 0; 84 }
方法二:声明一个数组.记录每个点的优先级.
同样是这个图,若遍历顺序为3 1 2 4 5
3的优先级为1 ,他的下一个点4的优先级则改为3的优先级+1.即4的优先级为2
同样可求2的优先级为2,当2找打4时,把4的优先级更新为3.
priority[当前点的next] = max( priority[当前点]+1 , priority[当前点的next] );
//View Code
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 const int MAX = 10000 + 10; 6 int in_degree[MAX] = {0}; 7 bool used[MAX] = {0}; 8 int priority[MAX]; 9 int sum; 10 int find_zero(int n) 11 { 12 int i; 13 for(i=1;i<=n;i++) 14 { 15 if(!used[i] && in_degree[i] == 0) 16 { 17 used[i] = 1; 18 sum = sum + 888 + priority[i]; 19 return i; 20 } 21 } 22 return -1; 23 } 24 int main() 25 { 26 int n,m; 27 while(cin>>n>>m) 28 { 29 int i,j; 30 vector <int> v[MAX]; 31 sum = 0; 32 memset(priority,0,sizeof(priority)); 33 memset(used,0,sizeof(used)); 34 memset(in_degree,0,sizeof(in_degree)); 35 for(i=1;i<=m;i++) 36 { 37 int a,b; 38 cin>>a>>b; 39 v[b].push_back(a); 40 in_degree[a]++; 41 } 42 int y_n = 1; 43 for(i=1;i<=n;i++) 44 { 45 int mark = find_zero(n); 46 if(mark == -1) 47 { 48 y_n = 0; 49 break; 50 } 51 else 52 { 53 for(j=0;j<v[mark].size();j++) 54 { 55 in_degree[v[mark][j]]--; 56 priority[v[mark][j]] = max(priority[mark]+1,priority[v[mark][j]]); 57 } 58 } 59 } 60 if(y_n == 0) 61 { 62 cout<<"-1"<<endl; 63 64 } 65 else 66 { 67 cout<<sum<<endl; 68 } 69 } 70 return 0; 71 }