Floyd--P2419 [USACO08JAN]牛大赛Cow Contest
FJ的$N(1 <= N <= 100)$头奶牛们最近参加了场程序设计竞赛:)。在赛场上,奶牛们按1..N依次编号。每头奶牛的编程能力不尽相同,并且没有哪两头奶牛的水平不相上下,也就是说,奶牛们的编程能力有明确的排名。 整个比赛被分成了若干轮,每一轮是两头指定编号的奶牛的对决。如果编号为A的奶牛的编程能力强于编号为B的奶牛$(1 <= A <= N; 1 <= B <= N; A != B)$ ,那么她们的对决中,编号为A的奶牛总是能胜出。 FJ想知道奶牛们编程能力的具体排名,于是他找来了奶牛们所有 $M(1 <= M <= 4,500)$轮比赛的结果,希望你能根据这些信息,推断出尽可能多的奶牛的编程能力排名。比赛结果保证不会自相矛盾。
看到$n<=100$按$floyd$的$n^3$做法还是可以的,毕竟$floyd$代码简略且少。
首先思考这道题,怎样才能确定一头牛的名次,显然是他与其他所有牛的输赢关系都确定。因为只有输赢两种情况,所以我们只要记录赢得情况就可以。输入$a$和$b$,$s[a][b]=1$表示$a$赢了$b$。这样预处理之后,就开始跑$floyd$。$floyd$代码如下(下面有解释):
1 void Floyd() 2 { 3 for (int t = 1;t <= n;t++) 4 { 5 for (int i = 1;i <= n;i++) 6 { 7 for (int j = 1;j <= n;j++) 8 { 9 if (s[i][t]&&s[t][j]) 10 s[i][j]=1; 11 } 12 } 13 } 14 }
这里的t可以看做一个中转节点,如果i赢了t,且t赢了j,那么i就赢了j,这种简单逻辑还是可以推导出来的。然后我们就可以开始统计答案了。考虑一个问题,怎样知道两头牛之间的关系是否确定,s[i][j]=1表示i赢了j,两头牛的关系是确定的,s[j][i]=1表示j赢了i,两头牛的关系也是确定的,但是如果s[i][j]=0&&s[j][i]=0并不是说i输给了j,j输给了i,这显然是不成立的,而是根本没有确定。由于之前说过的,确定一头牛的名次根据是,他和所有牛的输赢关系都确定,所以只要有一个不确定我们就直接跳到下一个牛开始判断。这部分代码:
1 for(int i = 1;i <= n;i++) 2 { 3 int f=1; 4 for (int j = 1;j <= n;j++) 5 { 6 if (i==j)continue; 7 if (s[i][j]==0&&s[j][i]==0) 8 { 9 f=0; 10 break; 11 } 12 } 13 if (f==1) 14 ans++; 15 }
整个代码:
1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 #include <iostream> 5 #include <cstring> 6 using namespace std; 7 int n,m,a,b; 8 int s[1000][1000]; 9 int read() 10 { 11 int x=1,a=0; 12 char ch=getchar(); 13 while (ch < '0'||ch > '9') 14 { 15 if (ch == '-') x=-1; 16 ch = getchar(); 17 } 18 while (ch <= '9'&&ch >= '0') 19 { 20 a=a*10 + ch - '0'; 21 ch=getchar(); 22 } 23 return x*a; 24 } 25 void Floyd() 26 { 27 for (int t = 1;t <= n;t++) 28 { 29 for (int i = 1;i <= n;i++) 30 { 31 for (int j = 1;j <= n;j++) 32 { 33 if (s[i][t]&&s[t][j]) 34 s[i][j]=1; 35 } 36 } 37 } 38 } 39 int main() 40 { 41 int ans=0; 42 n=read(); 43 m=read(); 44 for (int i = 1;i <= m;i++) 45 { 46 a=read(); 47 b=read(); 48 s[a][b]=1; 49 } 50 Floyd(); 51 for(int i = 1;i <= n;i++) 52 { 53 int f=1; 54 for (int j = 1;j <= n;j++) 55 { 56 if (i==j)continue; 57 if (s[i][j]==0&&s[j][i]==0) 58 { 59 f=0; 60 break; 61 } 62 } 63 if (f==1) 64 ans++; 65 } 66 cout<<ans; 67 return 0; 68 }