HDU - 1704 - ランク(推移閉包をフロイド)

[リンクのタイトル](https://vjudge.net/contest/364766#problem/C)
影響を受ける:各2つの点間の唯一の関係の両側を表し、関係は推移的である、との間にどのように多くの点を尋ねそれは関係ありません。
  解決するために推移閉包問題をこのように使用します。私たちは、入力に応じてタイトルを取得することができます\(A-> B \)エッジを示し、\(A \)ウィン\(B \) そして私たちが確立し有効にすることができます\(<-b \)側を、表現\(B \)失われた\(\) 次いで4の合計の場合には、。
  1.場合(A-> B-> C \)\、それを導出することができる\(A \)ウィン\(C \)
  2.場合(A <-b <-C \)\、それが由来することができる(A \)\失わ\(C \)
  3.もし\(A-> B <-c \ ) 、我々はリリースすることはできません\(A \)\(C \)の関係を。
  4.場合(A <-B-> C \)\、我々は導入することができません\(\)\(C \)の関係。
  上記のいくつかのケースから、我々は、同じ転写方向にのみ関係することを、我々はこのパスではなく、その逆を介して2つの経路の間の関係を得ることができる見ることができます。したがって、我々は、発現した。1 \(A \)ウィン\(B \)で表さ-1 \(A \)失われた\(B \)でフロイドを求める
2点。

int n, m, g[maxn][maxn];
void init() {
    for (int i = 1; i<=n; ++i)
        for (int j = 1; j<=n; ++j)
            g[i][j] = 0;
}
void floyd() {
    for (int k = 1; k<=n; ++k)
        for (int i = 1; i<=n; ++i)
            if (g[i][k])
                for (int j = 1; j<=n; ++j)
                    if (!g[i][j] && g[i][k] && g[k][j] && g[i][k]==g[k][j])
                        g[i][j] = g[i][k];
}
int checker() {
    int ans = 0;
    for (int i = 1; i<=n; ++i)
        for (int j = i+1; j<=n; ++j)
            if (!g[i][j]) ++ans;
    return ans;
}
int main(void) {
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        init();
        for (int i = 0, a, b; i<m; ++i) {
            scanf("%d%d", &a, &b);
            g[a][b] = 1;
            g[b][a] = -1;
        }
        floyd();
        printf("%d\n", checker());
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/shuitiangong/p/12586564.html