hdu2647 Reward 拓扑排序

  此题的关键在于分层次,最低一层的人的奖金是888,第二层是888+1 ……

  分层可以这样实现。建立反向图。在拓扑排序的时候,第一批入度为0的点就处于第一层,第二批处于第二层 ……

  由于是逐个遍历入度为0的点,所以怎么实现上面所说的第一批,第二批就需要动点脑。

  可以试试下面的测试数据:

4 3
1 3
2 3
4 3


4 3
1 2
2 3
4 3

4 2
1 2
3 4

6 3
1 2
3 4
5 6

 

测试结果依次是:  3555  3556  3554   5331

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N = 10100, M =20010;
 7 struct node
 8 {
 9     int to,  next;
10 };
11 node edge[M];
12 int ind[N], head[N],que[N],ans[N];
13 int iq,tot,t;
14 void topo(int n)
15 {
16     int i,k,j=0,x,y;
17     t=-1;x=0;
18     for(i=1;i<=n;i++)
19         if(ind[i]==0) que[j++]=i;
20     ans[++t]=j-x;
21     y=0;
22     x=j;
23     for(i=0;i<j;i++)
24     {
25         if(i==ans[t]+y)
26         {
27             ans[++t]=j-x;
28             x=j;
29             y=i;
30         }
31 
32         int u=que[i];
33         for(k=head[u]; k!=-1; k=edge[k].next)
34         {
35             ind[edge[k].to]--;
36             if(ind[edge[k].to]==0)
37                 que[j++]=edge[k].to;
38         }
39     }
40     iq=j;
41 }
42 void addedge(int i,int j)
43 {
44     edge[tot].to=j;edge[tot].next=head[i];head[i]=tot++;
45 }
46 void init()
47 {
48     tot=0;
49     memset(ind,0,sizeof(ind));
50     memset(head,-1,sizeof(head));
51 }
52 int main()
53 {
54     //freopen("test.txt","r",stdin);
55     int n,m,i,j,k;
56     while(scanf("%d%d",&n,&m)!=EOF)
57     {
58         init();
59         int flag=0;
60         while(m--)
61         {
62             scanf("%d%d",&i,&j);
63             if(i==j) flag=1;
64             if(flag) continue;
65             ind[i]++;
66             addedge(j,i);
67         }
68         topo(n);
69         if(iq<n||flag) printf("-1\n");
70         else
71         {
72             int s=0;
73             for(i=0;i<=t;i++) s+=ans[i]*(i+888);
74             printf("%d\n",s);
75         }
76     }
77     return 0;
78 }
View Code

 

posted @ 2014-08-31 15:57  pengmq  阅读(217)  评论(0编辑  收藏  举报