poj3660(Cow Contest)解题报告

Solution:

传递闭包

//if a beats b and b beats c , then a beats c

//to cow i, if all the result of content(n-1) has been known,
    //then the rank can be determined

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <stdbool.h>
 4 #define maxn 1000
 5 
 6 //if a beats b and b beats c , then a beats c
 7 
 8 int main()
 9 {
10     long n,m,i,j,k,a,b,ans,total=0;
11     bool vis[maxn][maxn];
12     scanf("%ld%ld",&n,&m);
13     for (i=1;i<=n;i++)
14         for (j=1;j<=n;j++)
15             vis[i][j]=false;
16     for (i=1;i<=m;i++)
17     {
18         scanf("%ld%ld",&a,&b);
19         vis[a][b]=true;
20     }
21     for (i=1;i<=n;i++)
22         for (j=1;j<=n;j++)
23                 for (k=1;k<=n;k++)
24                     vis[j][k]=vis[j][k] || (vis[j][i] && vis[i][k]);
25     //to cow i, if all the result of content(n-1) has been known,
26     //then the rank can be determined
27     for (i=1;i<=n;i++)
28     {
29         ans=0;
30         for (j=1;j<=n;j++)
31             if (vis[i][j] || vis[j][i])
32                 ans++;
33         if (ans==n-1)
34             total++;
35     }
36     printf("%ld
",total);
37     return 0;
38 }

传递闭包标程+解释:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <stdbool.h>
 4 #define maxn 1000
 5 
 6 //n个点,点编号为1~n,m条边
 7 //传递闭包:判断图中任意两点是否可达
 8 //时间复杂度:n*n*n
 9 
10 int main()
11 {
12     long n,m,i,j,k,a,b;
13     bool vis[maxn][maxn];
14     scanf("%ld%ld",&n,&m);
15     for (i=1;i<=n;i++)
16         for (j=1;j<=n;j++)
17             vis[i][j]=false;
18     for (i=1;i<=m;i++)
19     {
20         scanf("%ld%ld",&a,&b);
21         vis[a][b]=true;
22     }
23     //如果是无向图,a能到达b意味着b也能到达a,所以可以求a->b(a<b),i<j<k
24     //如果没有if:操作n*n*n
25     //如果有if:判断n*n+n*(n-1)*n次,操作n*(n-1)*(n-2)
26     //所以直接不用if
27     //从j点到k点:从j到k经过的点的编号小于等于i(i=1,2,…,n)。当然也可以从j直达到k。
28     for (i=1;i<=n;i++)
29         for (j=1;j<=n;j++)
30             //if (i!=j)
31                 for (k=1;k<=n;k++)
32                     //if (i!=j && i!=k)
33                     vis[j][k]=vis[j][k] || (vis[j][i] && vis[i][k]);
34                         //if (vis[j][i] && vis[i][k])
35                             //vis[j][k]=true;
36     for (i=1;i<=n;i++)
37     {
38         printf("%ld : ",i);
39         for (j=1;j<=n;j++)
40             if (vis[i][j])
41                 printf("%ld ",j);
42         printf("
");
43     }
44     return 0;
45 }
46 /*
47 5 5
48 1 2
49 2 3
50 1 3
51 4 5
52 5 3
53 */

其实传递闭包跟floyd很像,原理都是一样的。

原文地址:https://www.cnblogs.com/cmyg/p/6676973.html