私の連絡先情報
郵便メール:
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
目次
フロイド アルゴリズム (フロイド ウォーシャル アルゴリズムの正式名) は、グラフ内の頂点のすべてのペア間の最短経路問題を解くために使用される動的計画法アルゴリズムです。これは重み付き有向グラフに適しており、負の重みエッジを処理でき (ただし、負の重みサイクルを含むグラフは処理できません)、グラフ内に負の重みサイクルがあるかどうかを検出できます。
フロイドのアルゴリズムの核となる考え方は動的計画法であり、その基本的な手順は次のとおりです。
フロイドのアルゴリズムの実装では通常、三重ループが使用され、外側のループはすべての中間頂点 k を走査し、内側の 2 つのループはすべての頂点ペア (i, j) を走査して、より短いパスがあるかどうかを確認します。
n 個の頂点を含む重み付きグラフ G があると仮定すると、2 次元配列を使用できます。dist[][]
頂点の各ペア間の最短パス長を保存します。当初は、dist[i][j]
i と j の間に直接接続されたエッジがない場合、 はグラフ内の直接接続されたエッジの重みに設定されます。dist[i][j]
無限大に設定します (到達不能を示します)。
初期化 : n×n 行列 D を作成します。ここで、D[i][j] はグラフ内の i から j までの直接エッジの重みに初期化されます。または、i と j の間に直接エッジがない場合は無限大に設定されます。対角要素 D[i][i] = 0。
動的プログラミング : 各頂点 k について (中間頂点として)、頂点 i と j の各ペア間の最短パスを更新します。k を中間点として、より短いパスを取得することが可能です。更新式は次のとおりです: D[i][j] = min(D[i][j], D[i][k] + D[k][j])。これは、k を中間頂点として i から j までの経路が短くなった場合、D[i][j] を更新することを意味します。
結果出力: n ラウンドの反復の後、行列 D の各要素 D[i][j] は、i から j への最短経路長になります。
- #include <algorithm>
- #include <bits/stdc++.h>
- #include <iostream>
- using namespace std;
-
- #define PII pair<int, int>
- #define fi first
- #define se second
- #define endl 'n'
- map<int, int> mp;
-
- const int N = 210, mod = 1e9 + 7;
- int T, n, m, k;
- int a[N], dist[N][N];
- PII ans[N];
-
- void floyd(int x) // 以 x 为中转点,更新其他点。
- {
- for (int i = 1; i <= n; i++)
- for (int j = 1; j <= n; j++)
- dist[i][j] = min(dist[i][j], dist[i][x] + dist[x][j]);
- }
-
- bool pd() // 判断是否所有点都已确定
- {
- for (int i = 1; i <= n; i++) {
- int cnt = 0;
- for (int j = 1; j <= n; j++)
- if (dist[i][j] != 1e9)
- cnt++; // 当前点能到达的点数
- ans[i] = {cnt, i};
- for (int j = 1; j <= n; j++)
- if (i != j && dist[j][i] != 1e9)
- cnt++; // 能到达当前点的点数
- if (cnt != n)
- return 0;
- }
- sort(ans + 1, ans + n + 1);
- return 1;
- }
-
- int main() {
- while (cin >> n >> m && n) {
- for (int i = 1; i <= n; i++)
- for (int j = 1; j <= n; j++)
- if (i != j)
- dist[i][j] = 1e9;
-
- int flag = 0;
- for (int i = 1; i <= m; i++) {
- char a, t, b;
- cin >> a >> t >> b;
- int x = a - 'A' + 1, y = b - 'A' + 1; // 现在要加一条从 y 到 x 的边
-
- if (!flag && dist[x][y] != 1e9) // 发现已经从x能到y,出现矛盾
- {
- printf("Inconsistency found after %d relations.n", i);
- flag = 1;
- }
-
- dist[y][x] = 1;
- floyd(x), floyd(y); // 分别以 x 和 y 为中转点更新其他点
- if (!flag && pd()) { // 发现所有点都已确定
- printf("Sorted sequence determined after %d relations: ", i);
- for (int i = 1; i <= n; i++)
- cout << char(ans[i].se + 'A' - 1);
- printf(".n");
- flag = 1;
- }
- }
- if (!flag)
- printf("Sorted sequence cannot be determined.n"); // 无法确定
- }
-
- return 0;
- }
dist
2 次元配列は無限大に初期化されます。これは、デフォルトでは不等式間に明確な順序関係がないことを意味します。dist
マトリックスは、フロイドのアルゴリズムを使用してすべての不等式間の最短経路を更新しますが、ここでは実際に「優先順位」または「順序付け」関係を更新しています。