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 }

 

你可能感兴趣的:(HDU)