题目链接: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;
}