题目: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 ",a[i]); 59 } 60 } 61 return 0; 62 } 63