HDU 2647 逆向拓扑排序

令每一个员工都有一个自己的等级level[i] , 员工等级越高,那么工资越高,为了使发的钱尽可能少,所以每一级只增加一单位的钱

输入a b表示a等级高于b,那么我们反向添加边,令b—>a那么in[a]++,再进行拓扑排序,每次都让边的终点的level值大于起始点,那么要用max取较大值

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 
 6 using namespace std;
 7 
 8 const int N = 10005;
 9 int n , m , level[N] ;
10 int first[N] , in[N] , k;
11 
12 struct Path{
13     int y , next;
14 }path[N<<2];
15 
16 void add_edge(int x, int y)
17 {
18     in[y]++;
19     path[k].y=y , path[k].next = first[x];
20     first[x] = k++;
21 }
22 
23 bool DAG()
24 {
25     memset(level,0,sizeof(level));
26     int cnt = 0;//统计能形成无环图的最多的点的个数
27     queue<int> q;
28     for(int i = 1; i<= n ; i++)
29         if(in[i] == 0){
30             q.push(i);
31             level[i] = 0;
32         }
33     while(true){
34         if(q.empty()) break;
35         int u = q.front();
36         q.pop();
37         cnt++;
38         for(int i = first[u] ; i!=-1 ; i=path[i].next){
39             int v= path[i].y;
40             in[v]--;
41             level[v] = max(level[v] , level[u]+1);
42             if(in[v] == 0)
43                 q.push(v);
44         }
45     }
46     if(cnt<n) return false;
47     return true;
48 }
49 
50 int main()
51 {
52    // freopen("a.in","rb",stdin);
53     int a,b;
54     memset(level , 0x3f , sizeof(level));
55     while(~scanf("%d%d",&n,&m)){
56         memset(first , -1 , sizeof(first));
57         memset(in , 0 , sizeof(in));
58         k=0;
59 
60         for(int i=0 ; i<m ; i++){
61             scanf("%d%d",&a,&b);
62             add_edge(b , a);
63         }
64 
65         if(DAG()){
66             int ans = 0;
67             for(int i = 1 ; i<=n ; i++)
68                 ans+=888+level[i];
69             printf("%d\n",ans);
70         }
71         else puts("-1");
72     }
73     return 0;
74 }

 

转载于:https://www.cnblogs.com/CSU3901130321/p/4101340.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值