POJ3660 row contest Floyd 传递闭包

题意:有n头牛,编号为1到n,牛比赛啦,现在给出其中一些牛的pk结果,问哪些牛的排名能够确定。

输入 n  m

      a   b

n头牛,给出m个比赛结果,

a  b 表示a打赢了b

一头牛,如果能够确定他的排名,则这头牛的入度和出度之和必定为n-1.

dis[i][j] 为1时表示从i能够到达j,即i的排名在j的前面。为0 时表示i,j不能确定。

a[i] 表示确定了排名在i前面的个数。

b[i] 表示确定了排名在i后面的个数。

首先用floyd扫一遍,确定了哪些点能够到达哪些点,

再扫一遍,求出a,b数组的值,

再扫一遍,找出满足a[i]+b[i]+1==n的点i的个数。

 1 #include<cstdio>

 2 #include<cstring>

 3 const int maxn=110;

 4 int dis[maxn][maxn];

 5 int a[maxn];

 6 int b[maxn];

 7 void floyd(int n)

 8 {

 9     for(int k=1;k<=n;k++)

10         for(int i=1;i<=n;i++)

11             for(int j=1;j<=n;j++)

12                 dis[i][j]=dis[i][j]||(dis[i][k]&&dis[k][j]);

13 }

14 int query(int n)

15 {

16     for(int i=1;i<=n;i++)

17         for(int j=1;j<=n;j++)

18             if(i!=j&&dis[i][j]){

19                 a[i]++;

20                 b[j]++;

21             }

22     int ans=0;

23     for(int i=1;i<=n;i++)

24         if(a[i]+b[i]+1==n)

25             ans++;

26     return ans;

27 }

28 int main()

29 {

30     int n;

31     while(scanf("%d",&n)!=EOF){

32         int m,u,v;

33         scanf("%d",&m);

34         memset(dis,0,sizeof(dis));

35         memset(a,0,sizeof(a));

36         memset(b,0,sizeof(b));

37         for(int i=1;i<=m;i++){

38             scanf("%d%d",&u,&v);

39             dis[u][v]=1;

40         }

41         floyd(n);

42         printf("%d\n",query(n));

43     }

44     return 0;

45 }
View Code

 

你可能感兴趣的:(floyd)