POJ 3660 Cow Contest. (传递闭包)【Floyd】

<题目链接>

题目大意:

有n头牛, 给你m对关系(a, b)表示牛a能打败牛b, 求在给出的这些关系下, 能确定多少牛的排名。

解题分析:

首先,做这道题要明确,什么叫确定牛的排名。假设该牛被x头牛打败(直接或间接),同时它也有y头手下败将(直接或间接),当x+y=n-1时,即除这头牛本身外,其他所有的牛都为这头牛贡献了出度或者入度。即,当这头牛与其它所有的牛的输赢关系都确定时(直接或间接),这头牛的排名也就可以确定了。而题目只给出了一些牛的直接输赢关系,这时,我们就可以利用Floyed算法,得到牛群之间的间接输赢关系。

比如:a-->b ,b-->c  ,则 a-->c,这种传递关系的思想,在Floyed 的三重循环中可以很轻易的体现,如果不明白就自己画图感受一下。

#include <cstdio>
#include <cstring>

int main(){
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF){
        int line[110][110];         //line[i][j]  表示 i 赢 j 
        memset(line,0,sizeof(line));
        for(int i=1;i<=m;i++){
            int a,b;
            scanf("%d %d",&a,&b);
            line[a][b]=1;        //输入的是能够直接确定输赢关系的点 
        }

        /* Floyed -传递闭包 */
        
        //即,如果a-->b,b-->c的话,那么a-->c
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                for(int k=1;k<=n;k++){
                    if(line[j][i]&&line[i][k]){
                        line[j][k]=1;
                    }
                }
            }
        }
        //用Floyed算法将那些间接的输赢关系也全部计算出来 
        
        int ans=0;
        for(int i=1;i<=n;i++){
            bool flag=true;
            for(int j=1;j<=n;j++){
                if(i==j)continue;
                if(!line[i][j]&&!line[j][i])flag=false;      //如果除它自己以外,还存在不能够和它确定输赢的点(直接或间接),那么这个点的位置不能够确定 
            }
            if(flag){
                ans++;
            }
        }
        printf("%d
",ans);
    }
    return 0;
}

2018-08-27

原文地址:https://www.cnblogs.com/00isok/p/9544771.html