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
",query(n));
43     }
44     return 0;
45 }
View Code
原文地址:https://www.cnblogs.com/-maybe/p/4370112.html