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很像,原理都是一样的。