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 }

 

posted @ 2020-02-17 21:41  小又又  阅读(229)  评论(1编辑  收藏  举报