和吴昊一起玩推理 Round 7 —— 推理逻辑中的传递闭包(HDOJ 1704)

 

如图所示,此为哲学家亚里士多德,以下给出他的三段论——三段论 (syllogism)是传统逻辑中的一类主要推理。又称直言三段论。古希腊哲学家亚里士多德首先提出了关于三段论的系统理论。形式逻辑间接推理的基本形式之一,由大前提小前提推出结论。如‘凡金属都能导电’(大前提),‘铜是金属’(小前提),‘所以铜能导电’(结论)。这称为三段论法或三段论式。三段论属于一种演绎逻辑,是不同于归纳逻辑的,具有较强的说服力。

  当然,三段论的使用是有一定条件的,比如,就两场比赛而言,A赢了B,B赢了C,不能由此得到A赢了C,毕竟,A和C之间还没有比过。但是,在数字之间是可以进行这样的比较的没有错。比如,A比B多3,B比C多4,那么,至少是A比C要多没有错。

 (HDOJ 1704)有n个人和m场比赛,输出在这n个人中有多少场的比赛是不能确定的,并规定了

  if A wins B, and B wins C, then A wins C. ask A B, and ask B A is the same;

  求对于一个特定的TEAM来说,每场比赛结束之后,还有多少场“可能”的“预测比赛”是胜负未定的?

  对于传递闭包来说,其时间复杂度O(n^3),只要500个数据量就会超时1S(这里还不包括样例的数目),这也就是传递闭包的缺陷吧,不过,使用起来还是相当方便的,这里给出Source,以及传递闭包的具体应用(我这里会加粗显示出来的)

 

 1  #include <stdio.h>
 2  #include <string.h>
 3 
 4  int s[601][601]; //为传递闭包准备的二维数组
 5 
 6  int main( )
 7  {
 8    int p,q,n,m,t;
 9    int count ;
10    int i , j , k , c ;
11    scanf( "%d" , &t ) ;
12    while( t -- )
13    {
14      memset( s , 0 , sizeof( s ) ) ;
15      scanf( "%d %d" , &n , &m ) ;
16      n++ ;
17      top = 1 ;
18      for( c = 0 ; c < m ; c ++ )
19      {
20        scanf( "%d %d" , &i , &j ) ;
21        //第i人可以胜过第j人
22        s[i][j] = 1 ;
23        s[j][i] = -1 ;
24      }
25      count = 0 ;
26 
27      //闭包处理的整个过程
28      for( k = 1 ; k < n ; k ++ )
29      {
30        for( i = 1 ; i < n ; i ++ )
31        {
32          if( s[i][k] > 0 )
33          for( j = 1 ; j < n ; j ++ )
34          {
35            if( s[k][j] > 0 )
36            {
37              s[i][j] = 1 ; s[j][i] = -1 ;
38            }
39          }
40        }
41      }
42      for( i = 1 ; i < n ; i ++ )
43      {
44        for( j = i+1 ; j < n ; j ++ )
45        {
46          //逐一扫描,对于胜负未分的情况
47          if( !s[i][j] )
48            count ++ ;
49        }
50      }
51      printf( "%d\n" , count ) ;
52    }
53    return 0 ;
54  }

 

 

posted on 2013-02-27 22:41  吴昊系列  阅读(179)  评论(0编辑  收藏  举报

导航