N (≤ 100) 隻牛,技能值互不相同。M (≤ 4500) 場比賽,結果為 A 勝 B。技能高者必勝。給出比賽結果,問有多少隻牛的**絕對排名**(即與所有其他牛的勝負關係均已知)可以被確定。保證結果無矛盾。
bool g[105][105]; // g[i][j] = i 勝 j
int deg[105]; // 確定關係計數
// 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][j] = true;
// 統計每頭牛的確定關係數
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
if (g[i][j]) { deg[i]++; deg[j]++; }
// 答案:deg[i] == n-1 的牛數
int ans = 0;
for (int i = 1; i <= n; ++i) if (deg[i] == n-1) ++ans;
#include
#include
using namespace std;
const int MAXN = 105;
bool g[MAXN][MAXN];
int deg[MAXN];
int main() {
int n, m;
while (~scanf("%d%d", &n, &m)) {
memset(g, 0, sizeof(g));
memset(deg, 0, sizeof(deg));
for (int i = 0; i < m; ++i) {
int a, b; scanf("%d%d", &a, &b);
g[a][b] = true;
}
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][j] = true;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
if (g[i][j]) { deg[i]++; deg[j]++; }
int ans = 0;
for (int i = 1; i <= n; ++i) if (deg[i] == n-1) ++ans;
printf("%d\n", ans);
}
return 0;
}
POJ 3660 是傳遞閉包的直接應用。N ≤ 100 時 Floyd 最簡潔;若 N 較大可用拓撲排序 + bitset 優化。關鍵洞見:排名確定 ⇔ 與所有其他點在閉包中可達或可達它。