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 }

 

posted @ 2012-09-10 15:43  zx雄  阅读(700)  评论(0编辑  收藏  举报