题解:洛谷 P2419 [USACO08JAN] Cow Contest S

【题目来源】

洛谷:[P2419 USACO08JAN] Cow Contest S - 洛谷

【题目描述】

FJ 的 \(N\)\(1 \leq N \leq 100\))头奶牛们最近参加了场程序设计竞赛。在赛场上,奶牛们按 \(1, 2, \cdots, N\) 依次编号。每头奶牛的编程能力不尽相同,并且没有哪两头奶牛的水平不相上下,也就是说,奶牛们的编程能力有明确的排名。整个比赛被分成了若干轮,每一轮是两头指定编号的奶牛的对决。如果编号为 \(A\) 的奶牛的编程能力强于编号为 \(B\) 的奶牛(\(1 \leq A, B \leq N\)\(A \neq B\)),那么她们的对决中,编号为 \(A\) 的奶牛总是能胜出。FJ 想知道奶牛们编程能力的具体排名,于是他找来了奶牛们所有 \(M\)\(1 \leq M \leq 4,500\))轮比赛的结果,希望你能根据这些信息,推断出尽可能多的奶牛的编程能力排名。比赛结果保证不会自相矛盾。

【输入】

第一行两个用空格隔开的整数 \(N, M\)

\(2\sim M + 1\) 行,每行为两个用空格隔开的整数 \(A, B\) ,描述了参加某一轮比赛的奶牛的编号,以及结果(每行的第一个数的奶牛为胜者)。

【输出】

输出一行一个整数,表示排名可以确定的奶牛的数目。

【输入样例】

5 5
4 3
4 2
3 2
1 2
2 5

【输出样例】

2

【算法标签】

《洛谷 P2419 Cow Contest》 #深度优先搜索DFS# #拓扑排序# #Floyd算法# #USACO# #2008#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

const int N = 105;           // 最大顶点数
int n, m;                    // n: 顶点数, m: 边数
int d[N][N];                 // 邻接矩阵,d[i][j]=1表示i可到达j
int ans;                     // 满足条件的顶点个数

/**
 * 传递闭包算法
 * 基于Floyd-Warshall思想,计算有向图的可达性
 * 如果i可到达k,且k可到达j,则i可到达j
 */
void floyd() 
{
    // 三重循环,k为中转点
    for (int k = 1; k <= n; k++) 
    {
        for (int i = 1; i <= n; i++) 
        {
            for (int j = 1; j <= n; j++) 
            {
                // 如果i可到达k,且k可到达j,则i可到达j
                if (d[i][k] && d[k][j])
                {
                    d[i][j] = 1;  // 标记i可到达j
                }
            }
        }
    }
}

int main()
{
    // 输入顶点数和边数
    cin >> n >> m;
    
    // 构建有向图
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        d[x][y] = 1;  // 有向边x→y
    }
    
    // 计算传递闭包
    floyd();
    
    // 统计满足条件的顶点个数
    for (int i = 1; i <= n; i++)
    {
        int s = 0;  // 统计与顶点i有可达关系的顶点数
        
        // 计算到达i的顶点数 + i到达的顶点数
        for (int j = 1; j <= n; j++)
        {
            s += d[j][i];  // 统计有多少顶点可到达i
            s += d[i][j];  // 统计i可到达多少顶点
        }
        
        // 如果i与其他n-1个顶点都有可达关系,计数加1
        if (s == n - 1)
        {
            ans++;
        }
    }
    
    // 输出满足条件的顶点个数
    cout << ans << endl;
    
    return 0;
}

【运行结果】

5 5
4 3
4 2
3 2
1 2
2 5
2
posted @ 2026-02-19 16:20  团爸讲算法  阅读(5)  评论(0)    收藏  举报