题目大意:有n只奶牛,参加一个比赛,给定m种关系(如A能打败B),求最后能确定其排名的奶牛个数?
解题思路:看到这种题就头大,显然一点思路没有~~~
结果又只能偷偷去看别人的题解,唉~~~
一只牛的排名在什么情况下可以确定呢,那就是已经确切地知道比它高的有几只、比它低的有几只,而且前后加起来正好是n-1时,那么它的排名就可以确定。
其实所给关系可以看作是一条路(从A走到B),我们只需判断出任意两点间是否导通,再确认一个点的入度与出度是否相加等于n-1,那么我们就可以判断这个点是否是我们需要求得点。
要判断任意两点是否导通,即全源最短路,而且是有向无权图,那么可以使用图的传递闭包,用一下Floyd
代码:
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <cmath>
#include <string>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define PB push_back
#define FOR(i,n,m) for(int i=n;i<=m;i++)
#define ROF(i,n,m) for(int i=n;i>=m;i--)
#define clr(i,j) memset(i,j,sizeof(i))
#define maxn 105
typedef long long ll;
typedef pair<int,int> pii;
const int inf =0x3f3f3f3f;
int n,m;
int dis[maxn][maxn];
int main()
{
while(~scanf("%d %d",&n,&m))
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
dis[i][j]=(i==j?1:0);
while(m--)
{
int a,b;
scanf("%d %d",&a,&b);
dis[a][b]=1;
}
for(int k=1; k<=n; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
dis[i][j]=dis[i][j]||(dis[i][k]&&dis[k][j]);
int ans=0;
for(int i=1; i<=n; i++)
{
int anw=0;
for(int j=1; j<=n; j++)
if(j!=i)
{
if(dis[i][j])
anw++;
if(dis[j][i])
anw++;
}
if(anw==n-1)ans++;
}
printf("%d\n",ans);
}
return 0;
}