C/C++の宿題のまとめ@Wiki

隣接行列から連結判定

最終更新:

匿名ユーザー

- view
管理者のみ編集可
162 :デフォルトの名無しさん :2005/11/01(火) 17:20:58
[1] 授業単元:プログラム演習&情報数学
[2] 問題文(含コード&リンク):
隣接行列を入力して、連結かどうかを判定するプログラムを作成せよ。
連結かどうかの判定は、隣接行列をA、 位数(頂点の数)をmとしたとき、
A+A^2+…+A^(m-1) の成分に0があるものが連結ではないと言える。

[3] 環境
 [3.1] OS: Linux
 [3.2] コンパイラ名とバージョン: gcc
 [3.3] 言語: C
[4] 期限: 2005年11月3日まで
[5] その他の制限: 特に無し

以上の内容なのですが、分かる方がいましたら教えてください。
よろしくお願いします。

163 :デフォルトの名無しさん :2005/11/01(火) 17:24:50
>>162
ちょっと用語がおかしいかも知れないが、ホップ数m-1以下で
到達する経路の無い奴が有るかどうか調べろってこと?

とりあえず行列のn乗返す関数作ってくる

164 :162:2005/11/01(火) 17:32:38
>>163
はい、そういう意味の問題です。

165 :デフォルトの名無しさん :2005/11/01(火) 17:56:36
>>162 163 じゃないけどさくっと書いちゃったのでうp
#include <stdio.h>
#define m 5
int main() {
 int i, j, k, l;
 int A[m][m], B[m][m], C[m][m], tmpB[m][m];
 /* 初期化 (C: 0,B: 単位行列) */
 for (i = 0; i < m; ++i) {
  for (j = 0; j < m; ++j)
   A[i][j] = B[i][j] = C[i][j] = 0;
  B[i][i] = 1;
 }
 /* 連結してるところを 1 ,その他を 0 に設定 */
 A[0][1] = A[0][2] = A[2][3] = A[3][4] = A[3][1] = A[4][2] = 1;

166 :デフォルトの名無しさん :2005/11/01(火) 17:59:36
 for (l = 1; l <= m-1; ++l) { /* C = sum_k A^k */
  for (i = 0; i < m; ++i)
   for (j = 0; j < m; ++j)
    for (k = 0, tmpB[i][j] = 0; k < m; ++k)
     tmpB[i][j] += B[i][k] * A[k][j]; /* B = A^k は前の値を使って計算 */
  for (i = 0; i < m; ++i)
   for (j = 0; j < m; ++j)
    B[i][j] = tmpB[i][j], C[i][j] += B[i][j];
 }
 for (i = 0; i < m; ++i)
  for (j = 0; j < m; ++j)
   if (C[i][j] == 0)
    printf("%d -> %d cannot approve\n", i, j);
}

オーダーは for 文を数えればわかるように O(V^4).
Floyd Warshall あたりを使えば O(V^3) でできるはずなので,不利なアルゴリズムと思う.

167 :165:2005/11/01(火) 18:02:00
>>165 コメントがミスリーディングだった.C = sum_k A^l.

168 :165:2005/11/01(火) 18:03:11
>>167 C = sum_l A^l 俺氏ね
目安箱バナー