poj 3687(拓扑排序)
http://poj.org/problem?id=3687
题意:有一些球他们都有各自的重量,而且每个球的重量都不相同,现在,要给这些球贴标签。如果这些球没有限定条件说是哪个比哪个轻的话,那么默认的前面比后的要请,而且这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 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 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<int >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 }