标签:c++
链接:
题意:
有N个标号为1~N的小球,重量(不包括断言)依次增加 ,现给出M句断言 ,断言格式为a b
表示小球a轻于小球b 要求根据重量大小依次输出1~N号小球应在的的位置(重量递增)不满足断言则输出-1
题解:
因为重量是依次增加的 不能按常规的构造edge[a][b]=1生成拓扑排序
既然关系格式和一般拓扑排序是相反的 我们可以尝试着构造反向边edge[b][a]=1;
indegree[a]++; 再根据小球标号从后往前进行拓扑排序,即可得到一幅完整的从大
到小的拓扑排序。
注意:
1.题目要求输出1~N号小球的位置,而不是完整的拓扑排序。
2.再构造边edge[b][a]=1的时候不能进行indegree[a]++;因为会有重边。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int map[505][505]; int indegree[505]; int ans[505]; int m; int topsort() { int i,j,loc,k=m; for(i=0; i<m; i++) { for(j=m; j>0; j--) //从后往前 if(!indegree[j]) { loc=j; break; } if(j==0) return 0; ans[loc]=k--; //ans[k--]=loc; indegree[loc]=-1; for(j=1; j<=m; j++) if(map[loc][j]) indegree[j]--; } return 1; } int main() { int i,j,t,a,b,n; scanf("%d",&t); while(t--) { memset(indegree,0,sizeof(indegree)); memset(map,0,sizeof(map)); scanf("%d%d",&m,&n); while(n--) { scanf("%d%d",&a,&b); map[b][a]=1; } for(i=1;i<=m;i++) for(j=1;j<=m;j++) if(map[i][j]) indegree[j]++; if(topsort()) { for(i=1; i<m; i++) cout<<ans[i]<<' '; cout<<ans[i]<<endl; } else cout<<-1<<endl; } return 0; }
POJ 3687 Labeling Balls 逆向拓扑排序
标签:c++
原文地址:http://blog.csdn.net/axuan_k/article/details/43016345