poj 3660 Cow Contes floyd 传递闭包

缘起

日常浪费生命 poj 3660 Cow Contes

分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
有n头牛比赛,m种比赛结果,最后问你一共有多少头牛的排名被确定了,
其中如果a战胜b,b战胜c,则也可以说a战胜c,即可以传递胜负。

【输入】
两个正整数 N 和 M.
然后是M行,每行 A B, A是赢家
1 ≤ N ≤ 100
1 ≤ M ≤ 4,500
1 ≤ A ≤ N; 1 ≤ B ≤ N; A ≠ B

【输出】
多少头牛的排名确定了

【样例输入】
5 5
4 3
4 2
3 2
1 2
2 5

【样例输出】
2

【限制】
1s

牛x排名确定的意思是,x击败的牛的头数+击败x的牛的头数=n-1. 而胜负有传递性. 如果将牛视作图中的顶点.

g[A][B]=1表示A击败了B,而g[B][A] = -1. 所以我们要将这种±1的关系传递出去. 形成闭包.

怎么传递闭包呢? 采用floyd最短路算法的思想即可.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//#include "stdafx.h"

#include <stdio.h>
//#define LOCAL

int n,m,g[105][105];

void floyd()
{
for (int k = 1; k<=n;k++)
{
for (int i = 1; i<=n;i++)
{
for (int j = 1; j<=n;j++)
{
if (g[i][k] == g[k][j] && g[i][k]) // 不能漏掉 g[i][k] 这个条件, 即只有两者皆为1或者-1, 则才能推导g[i][j],如果两者都是0的话, 则不能推断g[i][j]的关系的
{
g[i][j] = g[i][k];
}
}
}
}
}

int main() {

#ifdef LOCAL
freopen("d:\\data.in", "r", stdin);
//freopen("d:\\my.out", "w", stdout);
#endif
scanf("%d%d", &n, &m);
while(m--)
{
int a,b;
scanf("%d%d", &a, &b);
g[a][b] = 1, g[b][a] = -1; // a击败b, 1表示击败, -1表示负于, 0表示不确定
}
floyd();
int ans = 0;
for (int i = 1,tot; i<=n;i++)
{
tot =0; // 这一行0的个数
for (int j = 1; j<=n;j++)
{
if (!g[i][j])
{
tot++;
}
}
ans+=(tot==1);
}
printf("%d\n", ans);
return 0;
}

ac情况

Status Accepted
Time 32ms
Memory 140kB
Length 815
Lang C++
Submitted 2019-09-08 13:48:32
Shared
RemoteRunId 20843245