题意:有一些球他们都有各自的重量,而且每个球的重量都不相同,现在,要给这些球贴标签。如果这些球没有限定条件说是哪个比哪个轻的话,那么默认的前面比后的要请,而且这n个球的重量也正好是分布在1-n这个范围内,现在要你求出他们各自所占的重量。
思路:最开始,我也是想到了用拓扑排序,但是它的入度值我确定不了,然后去看discuss,里面说对每个判断条件反向建图,然后在用最大优先队列。我不理解这是什么意思。然后看了下别人的博客,模拟了一下大概的过程。
比如说
4 1
4 1
那么答案是2 3 4 1
反向建图,那么也就是digree[ 4 ] ++;
然后,其他的数入度值都是为0,所以都进优先队列。
那么现在优先队列就是有 1 2 3 这三个数。
然后,location[ 3 ] = 4;
再去寻找有没有与3相比较过的数。
然后, location[ 2 ] = 3;
再去找有没有与2相比较过的数。
然后,location[ 1 ] = 2;
再去找有没有与1比较过的数,如果有的话,把那么数入队列,那么4就入了队列。
然后,location[ 4 ] = 1;
然后反向输出,这就是结果,而那么 4 3 2 1 这是怎么来的呢,首先用一个变量num等于n。
然后每使用一次,这个变量就--。上面的也就是相当于 location[ 3 ] = 4 --。
1 #include2 #include 3 #include 4 #define maxn 210 5 6 using namespace std; 7 8 int digree [ maxn ]; //这个就是入度值。 9 int judge [ maxn ][ maxn ]; //这个是用来判断有没有重边的。10 int location [ maxn ];11 int m,n;12 13 priority_queue s; //这个是默认的最大优先队列。14 15 int topsort()16 {17 int num = n;18 for( int i = 1 ; i <= n ; i++ )19 if(!digree[ i ]) s.push( i );20 if( s.empty() ) return 0; //如果没有入度为0的,则说明构成了一个环。21 while( !s.empty() )22 {23 int tmp =s.top();24 s.pop();25 location [ tmp ] = num--;26 for( int i = 1 ; i <= n ; i++ )27 {28 if( judge[ i ][ tmp ] )29 {30 judge[ i ][ tmp ] = 0;31 digree[ i ] --;32 if( !digree[ i ] ) s.push( i );33 }34 }35 }36 if( num != 0 ) return 0; //如果这里Num 不能等于0,那么说明最少还有两个是无法确定的。37 return 1;38 }39 40 41 int main()42 {43 int t,a,b;44 scanf("%d",&t);45 while( t -- )46 {47 memset( digree , 0 , sizeof( digree ) );48 memset( judge , 0 , sizeof( judge ) );49 memset( location , 0 , sizeof( location ) );50 scanf("%d%d",&n,&m);51 for( int i = 1 ; i <= m ; i ++ )52 {53 scanf("%d%d",&a,&b);54 if(judge[ a ][ b ] > 0) continue; //判重。55 judge[ a ][ b ] = 1;56 digree [ a ] ++;57 }58 a = topsort();59 if( a ) {60 int i = 1;61 for( ; i < n ; printf("%d ",location[ i++ ]) );62 printf("%d\n",location[ i ]);63 }64 65 else printf("-1\n");66 }67 return 0;68 }