题目链接:
http://poj.org/problem?id=3687
题目大意:
现在有n个不同重量的球,球的重量是从1--n。需要给这个n个球从1--n进行编号。
要求就是编号为a的球的质量小于编号为b球的质量。
a和b有m组。
如果结果不止一种,使编号小的球对应的质量尽可能小。
最后输出1--n号球对应的质量。
解题思路:
拓扑排序。
建图的时候建逆向图
s[b][a]=1;
从大到小对球的重量i进行枚举,寻找重量i的编号k,k越大越好。
这样就能保证将质量小的留给编号小的。
注意事项,题目给的边可能出现自环,也可能出现重边。
源代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<cmath>
#include<vector>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
int s[205][205]; //邻接矩阵
int degree[205]; //统计每个顶点的度数
int key[205];
int n,m,flag;
void order()
{
int i,j,k,t,Max;
for(i=n;i>=1;i--) //质量,先将质量大的赋值给编号大的,那么最后就是质量小的赋值给了编号小的
{
k=n;
while(degree[k]!=0)
k--;
if(k==0) //没有找到这样的标签,非法
{
flag=1;
break;
}
key[k]=i;
degree[k]=-1;
for(j=1;j<=n;j++)
if(s[k][j])
degree[j]--;
}
return;
}
int main()
{
freopen("in.txt","r",stdin);
int cs,i,j,a,b;
scanf("%d",&cs);
while(cs--)
{
scanf("%d%d",&n,&m);
memset(s,0,sizeof(s));
memset(degree,0,sizeof(degree));
flag=0;
while(m--)
{
scanf("%d%d",&a,&b);
if(a==b) //不能出现重边
flag=1;
if(!s[b][a]) //出现重边的情况
{
s[b][a]=1;
degree[a]++;
}
}
if(flag==0)
order();
if(flag)
{
printf("-1\n");
continue;
}
for(i=1;i<n;i++)
printf("%d ",key[i]);
printf("%d\n",key[n]);
}
return 0;
}