title: Cow Contest 弗洛伊德+传递闭包 nyoj211
tags: [弗洛伊德,传递闭包]

题目链接

描述

N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is unique among the competitors.The contest is conducted in several head-to-head rounds, each between two cows. If cow A has a greater skill level than cow B (1 ≤ A ≤ N; 1 ≤ B ≤ N; A ≠ B), then cow A will always beat cow B.Farmer John is trying to rank the cows by skill level. Given a list the results of M (1 ≤ M ≤ 4,500) two-cow rounds, determine the number of cows whose ranks can be precisely determined from the results. It is guaranteed that the results of the rounds will not be contradictory.

  • 输入
    • Line 1: Two space-separated integers: N and M* Lines 2..M+1: Each line contains two space-separated integers that describe the competitors and results (the first integer, A, is the winner) of a single round of competition: A and BThere are multi test cases.The input is terminated by two zeros.The number of test cases is no more than 20.
  • 输出
    For every case:* Line 1: A single integer representing the number of cows whose ranks can be determined
  • 样例输入
    5 5
    4 3
    4 2
    3 2
    1 2
    2 5
    0 0
  • 样例输出
    2

分析:

使用Floyd算法来判断传递闭包。

首先使用Floyd算法来求出每两个点的最短路径

然后对于能否确定一个牛的位置的判断,我们假设现在一共有5个牛,对于牛A,如果有两个牛可以打败它并且它又可以打败其他的两个牛的话,我们就可以确定它的位置在3号。

所以对于N个牛,如果能打败它和它能打败的牛的总个数为N-1的话,那么它的位置就可以确定出来,这就叫做传递闭包(以前完全没有听说过)。

代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
#define INF 0x3f3f3f3f
int N,M;
int Tu[102][102];
void Floyd()///弗洛伊德算法,三重for循环
{
    for(int k=1; k<=N; k++)
        for(int i=1; i<=N; i++)
            for(int j=1; j<=N; j++)
            {
                if(i!=j&&Tu[i][k]!=INF&&Tu[k][j]!=INF&&Tu[i][j]>Tu[i][k]+Tu[k][j])
                    Tu[i][j]=Tu[i][k]+Tu[k][j];
            }
}
int main()
{
    int a,b;
    while(~scanf("%d%d",&N,&M),N,M)
    {
        memset(Tu,INF,sizeof(Tu));
        while(M--)
        {
            scanf("%d%d",&a,&b);
            Tu[a][b]=1;///表示的是a能战胜b
        }
        Floyd();
        int ans=0;
        int sum=0;
        for(int i=1; i<=N; i++)
        {
            sum=0;
            for(int j=1; j<=N; j++)
            {
                if(i!=j)
                {
                    if(Tu[i][j]!=INF)///i能战胜j
                        sum++;
                    if(Tu[j][i]!=INF)///j能战胜i
                        sum++;
                }
            }
            if(sum==N-1)
                ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}
posted on 2017-04-28 17:55  渡……  阅读(317)  评论(0编辑  收藏  举报