题目链接:http://poj.org/problem?id=3660

n头牛比赛,m种比赛结果,最后问你一共有多少头牛的排名被确定了,其中如果a战胜b,b战胜c,则也可以说a战胜c,即可以传递胜负。求能确定排名的牛的数目。

思路:如果一头牛被x头牛打败,打败y头牛,且x+y=n-1,则我们容易知道这头牛的排名就被确定了,所以我们只要将任何两头牛的胜负关系确定了,在遍历所有牛判断一下是否满足x+y=n-1,将满足这个条件的牛数目加起来就是所求解。

抽象为简单的floyd传递闭包算法,在加上每个顶点的出度与入度 (出度+入度=顶点数-1,则能够确定其编号)。

传递闭包的定义:

G的传递闭包定义为G*=(V,E*),其中E={(i,j):图G中存在一条从i到j的路径}。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <functional>
#include <map>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
using namespace std;
const int maxn=205;

int n, m;
int e[maxn][maxn]={0};
int s[maxn][2]={0};

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

}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int x, y;
        scanf("%d%d",&x,&y);
        e[x][y]=1;
    }
    floyd();
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            s[i][0]+=e[i][j];
            s[j][1]+=e[i][j];
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(s[i][0]+s[i][1]==n-1)
        {
            ans++;
        }
    }
    cout<<ans<<endl;

    return 0;
}