链接:
题意:
有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;
}