poj 3687 Labeling Balls(拓扑排序)

题目:http://poj.org/problem?id=3687
题意:n个重量为1~n的球,给定一些编号间的重量比较关系,现在给每个球编号,在符合条件的前提下使得编号小的球重量小。(先保证1号球最轻,其次2号……)

然后,按照重量1~n的输出位置

 要倒序建图,优先选择编号大的 给编号大的   拓扑排序,注意根据题的要求,要先保证1号球最轻,如果我们由轻的向重的连边,然后我们依次有小到大每次把重量分给一个入度为0的点,那么在拓扑时我们面对多个入度为0的点,我们不知道该把最轻的分给谁才能以最快的速度找到1号(使1号入度为0),并把当前最轻的分给1号。所以我们要由重的向轻的连边,然后从大到小每次把一个重量分给一个入度为0的点。这样我们就不用急于探求最小号。我们只需要一直给最大号附最大值,尽量不给小号赋值,这样自然而然就会把轻的重量留给小号。

 1 #include <iostream>
 2  #include<cstdio>
 3  #include<cstring>
 4  #include<cstdlib>
 5  #include<stack>
 6  #include<queue>
 7  #include<iomanip>
 8  #include<cmath>
 9  #include<algorithm>
10  using namespace std;
11  int main()
12  {
13      int t,i,j,n,m,u,v,k,f;
14      int r[3000],G[300][300],a[3000];
15      cin>>t;
16      while(t--)
17      {
18          k=0;
19          f=0;
20          cin>>n>>m;
21          memset(r,0,sizeof(r));
22          memset(G,0,sizeof(G));
23          while(m--)
24          {
25              cin>>u>>v;
26              if(!G[v][u])
27              {
28                  G[v][u] = 1;   //反向建图
29                  r[u]++;
30              }
31          }
32          for(i = n; i >= 1; i--) // 代表位置,倒序找最大的
33          {
34              for(j = n; j >= 1; j--) //代表球的重量,倒序找球的重量最大的
35              {
36                  if(!r[j])  //从最后开找
37                  {
38                      a[j]=i;
39                      r[j]--;
40                      for(k = 1; k <= n; k++)
41                          if(G[j][k])
42                              r[k]--;
43                      break;
44                  }
45              }
46              if(j==0)
47              {
48                  f=1;
49                  break;
50              }
51          }
52          if(f) cout<<"-1"<<endl;
53          else
54          {
55              for(i=1; i<n; i++)
56                  printf("%d ",a[i]);
57              if(n>=1)
58                  printf("%d\n",a[i]);
59          }
60      }
61      return 0;
62  }
63  

 

 

posted @ 2013-08-14 17:03  水门  阅读(240)  评论(0编辑  收藏  举报