POJ 3660 - Cow Contest ( floyed求传递闭包 )

题意

公牛比赛, 给出一些等级关系, 如 A B 表示 A 能够战胜 B
求有多少只公牛的排名能够确定

思路

一眼看成拓扑排序, 很久没做过拓扑忘了怎么写, 又因为个人赛不能查阅资料, 就没能继续想下去. 可是题目并没有要求具体的排序顺序. 在这道题中, 所谓战胜关系是可以传递下去的, 比如 A 战胜 B , B 战胜 C, 则 A 能够战胜 C. 典型的floyed求传递闭包
讲道理, 训练前刚就做了紫书P364-365的那个传递闭包(UVa247), 可是看到题目却没有深入想到它的正确解法, 说明思维太僵化, 而且也没有把这个算法理解到位.
突破点 : 通过做出传递闭包建图, 遍历一遍, 若某点的入度 + 出度 == n - 1 则该公牛的排名能够被确定

AC代码

//POJ 挂了 等AC后再来放代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 105;
int g[maxn][maxn];
int in[maxn], out[maxn];  //入度 出度
int n, m;

void floyed()
{
    for(int k = 1; k <= n; k++)
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                g[i][j] = g[i][j]||(g[i][k]&&g[k][j]);
}

int main()
{
    int a, b;
    scanf("%d%d",&n,&m);
    for(int i = 0; i < m; i++)
    {
        scanf("%d%d", &a, &b);
        g[a][b] = 1;
    }
    floyed();
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            if( g[i][j] )
            {
                out[i] += 1;
                in[j] += 1;
            }
    int ans = 0;
    for(int i = 1; i <= n; i++)
        if( out[i]+in[i] == n-1 )
            ans += 1;
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jinxisui/article/details/81166477