题目链接:http://poj.org/problem?id=3660
题意是有n头牛,然后有m次操作,每次操作有两个数表示A可以打败B,然后要给这n头牛排名,问可以确定几头牛的名次时确定的。
对于一头牛的排名我们需要知道有多少头牛(i)能打败我,我又能打败多少头(j),那么当i+j==n-1的时候,这头牛的名次就可以确定了,这里就需要用Floyd传递闭包的算法来实现。其实和Floyd很像,思路就是去记录x牛打败了y牛以后,然后在进行传递闭包的时候,就是去更新有没有i打败k,k又打败j的情况,那么i就间接的打败了j。最后统计i+j==n-1有多少个就好了。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 105
using namespace std;
int pre[maxn][maxn];
int ans[maxn];
int n,m;
inline int getInt(){
int w = 0,q = 0;
char ch = getchar();
while((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if(ch == '-') q = 1, ch = getchar();
while(ch >= '0' && ch <= '9') w = w * 10 + ch - '0', ch = getchar();
return q ? -w : w;
}
int main()
{
n = getInt();
m = getInt();
memset(pre,0,sizeof(pre));
memset(ans,0,sizeof(ans));
while(m--){
int x,y;
x = getInt();
y = getInt();
pre[x][y] = 1;
}
for(int k=1;k<=n;k++){ // Floyd
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(pre[i][k] && pre[k][j]){
pre[i][j] = 1;
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
ans[i] += pre[i][j];
ans[j] += pre[i][j];
}
}
int sum = 0;
for(int i=1;i<=n;i++){
if(ans[i] == n - 1) sum++;
}
printf("%d\n",sum);
return 0;
}