洛谷p2419[USACO08JAN]牛大賽Cow Contest

題目背景

[Usaco2008 Jan]

題目描述

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.

FJ的N(1 <= N <= 100)頭奶牛們最近參加了場程序設計競賽:)。在賽場上,奶牛們按1..N依次編號。每頭奶牛的編程能力不盡相同,並且沒有哪兩頭奶牛的水平不相上下,也就是說,奶牛們的編程能力有明確的排名。 整個比賽被分成了若干輪,每一輪是兩頭指定編號的奶牛的對決。如果編號爲A的奶牛的編程能力強於編號爲B的奶牛(1 <= A <= N; 1 <= B <= N; A != B) ,那麼她們的對決中,編號爲A的奶牛總是能勝出。 FJ想知道奶牛們編程能力的具體排名,於是他找來了奶牛們所有 M(1 <= M <= 4,500)輪比賽的結果,希望你能根據這些信息,推斷出儘可能多的奶牛的編程能力排名。比賽結果保證不會自相矛盾。

輸入輸出格式

輸入格式:
第1行: 2個用空格隔開的整數:N 和 M

第2..M+1行: 每行爲2個用空格隔開的整數A、B,描述了參加某一輪比賽的奶 牛的編號,以及結果(編號爲A,即爲每行的第一個數的奶牛爲 勝者)

輸出格式:
第1行: 輸出1個整數,表示排名可以確定的奶牛的數目

輸入輸出樣例

輸入樣例#1:
5 5
4 3
4 2
3 2
1 2
2 5
輸出樣例#1:
2
輸出說明:
編號爲2的奶牛輸給了編號爲1、3、4的奶牛,也就是說她的水平比這3頭奶
牛都差。而編號爲5的奶牛又輸在了她的手下,也就是說,她的水平比編號爲5的
奶牛強一些。於是,編號爲2的奶牛的排名必然爲第4,編號爲5的奶牛的水平必
然最差。其他3頭奶牛的排名仍無法確定。

分析

乍一看,似乎沒什麼思路。看一下題目描述,”如果編號爲A的奶牛的編程能力強於編號爲B的奶牛,那麼她們的對決中,編號爲A的奶牛總是能勝出。”
所以反過來,如果A與B對決勝利,則A的能力大於B的能力。
同時,如果a>b,b>c,則a>c;反之亦然
怎麼寫呢?
看數據規模:

(1 ≤ N ≤ 100)

一定是O(n^3)!
floyd可以完美解決。

先跑一遍floyd,再掃一遍看對於每個i,它與其他牛關係已經確定,則排名就確定了。

#include<stdio.h>
int main()
{
    int n,m,f[101][101];
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            f[i][j]=-1;//設爲未確定
    for(int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        f[a][b]=1;//1代表大於
        f[b][a]=0;//0代表小於
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                if(f[i][k]==1&&f[k][j]==1)f[i][j]=1;
                if(f[i][k]==0&&f[k][j]==0)f[i][j]=0;
            }//floyd
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int tmp=1;
        for(int j=1;j<=n;j++)
            if(f[i][j]!=-1)tmp++;
        if(tmp==n)ans++;
    }//累計個數
    printf("%d",ans);
    return 0;
}

總結

這題的確絕妙。floyd與最短路擺脫開來,這讓我們對floyd算法的更多用處有了一定的瞭解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章