グラフアルゴリズムのライブラリ[1]
グリッド
グリッド上のBFS(最短経路)
//各点のスタートからの距離を配列で返す //si,sj:スタートの座標 //スタートは壁ではない //辿り着けない:-1 vector<vector<int>>bfs_grid_pass(int si,int sj, vector<vector<char>>field) { vector<int>di; di = { 0,1,0,-1 }; vector<int>dj; dj = { 1,0,-1,0 }; int h = field.size(); int w = field[0].size(); vector<vector<int>> d(h, vector<int>(w, INF)); d[si][sj] = 0; queue<pair<int,int>> que; que.push(pair<int,int>(si, sj)); while (!que.empty()) { pair<int,int> pos = que.front(); que.pop(); int i = pos.first, j = pos.second; for (int k = 0; k < 4; k++) { int ni = i + di[k], nj = j + dj[k]; if (ni < 0 || ni >= h) continue; if (nj < 0 || nj >= w) continue; if (field[ni][nj] == '#') continue; if (d[ni][nj] > d[i][j] + 1) { d[ni][nj] = d[i][j] + 1; que.push(pair<int,int>(ni, nj)); } } } rep(i, h) { rep(j, w) { if (d[i][j] == INF) { d[i][j] = -1; } } } return d; }
コード例
//各点のスタートからの距離を配列で返す //si,sj:スタートの座標 //スタートは壁ではない //辿り着けない:-1 vector<vector<int>>bfs_grid_pass(int si,int sj, vector<vector<char>>field) { vector<int>di; di = { 0,1,0,-1 }; vector<int>dj; dj = { 1,0,-1,0 }; int h = field.size(); int w = field[0].size(); vector<vector<int>> d(h, vector<int>(w, INF)); d[si][sj] = 0; queue<pair<int,int>> que; que.push(pair<int,int>(si, sj)); while (!que.empty()) { pair<int,int> pos = que.front(); que.pop(); int i = pos.first, j = pos.second; for (int k = 0; k < 4; k++) { int ni = i + di[k], nj = j + dj[k]; if (ni < 0 || ni >= h) continue; if (nj < 0 || nj >= w) continue; if (field[ni][nj] == '#') continue; if (d[ni][nj] > d[i][j] + 1) { d[ni][nj] = d[i][j] + 1; que.push(pair<int,int>(ni, nj)); } } } rep(i, h) { rep(j, w) { if (d[i][j] == INF) { d[i][j] = -1; } } } return d; } void print_vector(vector<vector<int>>V) { rep(i, V.size()) { rep(j, V[i].size()) { cout << V[i][j]; if (j == V[i].size() - 1) { cout << endl; } else { cout << ' '; } } } } signed main() { int h, w; cin >> h >> w; int si, sj; cin >> si >> sj; vector<vector<char>>field(h, vector<char>(w)); rep(i, h) { rep(j, w) { cin >> field[i][j]; } } vector<vector<int>>d = bfs_grid_pass(si, sj, field); print_vector(d); }
入力
7 8
1 1
########
#......#
#.######
#..#...#
#..##..#
##.....#
########
出力
-1 -1 -1 -1 -1 -1 -1 -1
-1 0 1 2 3 4 5 -1
-1 1 -1 -1 -1 -1 -1 -1
-1 2 3 -1 11 10 11 -1
-1 3 4 -1 -1 9 10 -1
-1 -1 5 6 7 8 9 -1
-1 -1 -1 -1 -1 -1 -1 -1
グリッド上のBFS(色分け)
//0から始まる数字で色分けする //壁:-1 vector<vector<int>>bfs_grid_color(vector<vector<char>>field) { int color = 0; int h = field.size(); int w = field[0].size(); vector<vector<int>> COLOR(h, vector<int>(w, INF)); vector<int>di; di = { 0,1,0,-1 }; vector<int>dj; dj = { 1,0,-1,0 }; rep(si, h) { rep(sj, w) { if (field[si][sj] != '#') { if(COLOR[si][sj]==INF){ COLOR[si][sj] = color; queue<pair<int, int>> que; que.push(pair<int, int>(si, sj)); while (!que.empty()) { pair<int, int> pos = que.front(); que.pop(); int i = pos.first, j = pos.second; for (int k = 0; k < 4; k++) { int ni = i + di[k], nj = j + dj[k]; if (ni < 0 || ni >= h) continue; if (nj < 0 || nj >= w) continue; if (field[ni][nj] == '#') continue; if (COLOR[ni][nj] > COLOR[i][j] + 1) { COLOR[ni][nj] = color; que.push(pair<int, int>(ni, nj)); } } } color++; } } } } rep(i, h) { rep(j, w) { if (COLOR[i][j] == INF) { COLOR[i][j] = -1; } } } return COLOR; }
コード例
//0から始まる数字で色分けする //壁:-1 vector<vector<int>>bfs_grid_color(vector<vector<char>>field) { int color = 0; int h = field.size(); int w = field[0].size(); vector<vector<int>> COLOR(h, vector<int>(w, INF)); vector<int>di; di = { 0,1,0,-1 }; vector<int>dj; dj = { 1,0,-1,0 }; rep(si, h) { rep(sj, w) { if (field[si][sj] != '#') { if(COLOR[si][sj]==INF){ COLOR[si][sj] = color; queue<pair<int, int>> que; que.push(pair<int, int>(si, sj)); while (!que.empty()) { pair<int, int> pos = que.front(); que.pop(); int i = pos.first, j = pos.second; for (int k = 0; k < 4; k++) { int ni = i + di[k], nj = j + dj[k]; if (ni < 0 || ni >= h) continue; if (nj < 0 || nj >= w) continue; if (field[ni][nj] == '#') continue; if (COLOR[ni][nj] > COLOR[i][j] + 1) { COLOR[ni][nj] = color; que.push(pair<int, int>(ni, nj)); } } } color++; } } } } rep(i, h) { rep(j, w) { if (COLOR[i][j] == INF) { COLOR[i][j] = -1; } } } return COLOR; } void print_vector(vector<vector<int>>V) { rep(i, V.size()) { rep(j, V[i].size()) { cout << V[i][j]; if (j == V[i].size() - 1) { cout << endl; } else { cout << ' '; } } } } signed main() { int h, w; cin >> h >> w; vector<vector<char>>field(h, vector<char>(w)); rep(i, h) { rep(j, w) { cin >> field[i][j]; } } vector<vector<int>>COLOR(h, vector<int>(w)); COLOR = bfs_grid_color(field); print_vector(COLOR); }
入力
4 4
..#.
..#.
.#..
.#..
出力
0 0 -1 1
0 0 -1 1
0 -1 1 1
0 -1 1 1
グラフ
これ以降は隣接リストを使う
以前の記事で隣接リストに二次元vectorを使ったがsetを使った方が便利なので変える
※補足
隣接リストの作り方(重みなしグラフ)
setのvectorにする。
a bと入力されるとする
これは頂点aと頂点bが繋がっているということである。
コード
signed main() { int V;//頂点数 int E;//辺の数 cin >> V >> E; vector<set<int>>G(V);//隣接リスト for (int i = 0; i < E; i++) { int a, b; cin >> a >> b; G[a].insert(b); G[b].insert(a); } rep(i, V) { for (auto x : G[i]) { cout << x << ' '; } cout << endl; } }
入力
8 7
0 3
1 3
1 2
3 7
3 4
7 4
5 6
出力
3
2 3
1
0 1 4 7
3 7
6
5
3 4
BFS(最短経路)
//スタートからの距離を配列で返す //start:スタートの頂点番号 //辿り着けない:-1 vector<int>bfs_graph_pass(int start, vector<set<int>>G) { int V = G.size(); vector<int>dist(V, INF); queue<int> que; dist[start] = 0; que.push(start); while (!que.empty()) { int v = que.front(); que.pop(); for (auto nv : G[v]) { if (dist[nv] != INF)continue; dist[nv] = dist[v] + 1; que.push(nv); } } rep(i, V) { if (dist[i] == INF) { dist[i] = -1; } } return dist; }
コード例
//スタートからの距離を配列で返す //start:スタートの頂点番号 //辿り着けない:-1 vector<int>bfs_graph_pass(int start, vector<set<int>>G) { int V = G.size(); vector<int>dist(V, INF); queue<int> que; dist[start] = 0; que.push(start); while (!que.empty()) { int v = que.front(); que.pop(); for (auto nv : G[v]) { if (dist[nv] != INF)continue; dist[nv] = dist[v] + 1; que.push(nv); } } rep(i, V) { if (dist[i] == INF) { dist[i] = -1; } } return dist; } signed main() { int start; cin >> start; int V;//頂点数 int E;//辺の数 cin >> V >> E; vector<set<int>>G(V);//隣接リスト for (int i = 0; i < E; i++) { int a, b; cin >> a >> b; G[a].insert(b); G[b].insert(a); } vector<int>dist = bfs_graph_pass(start, G); rep(i, V) { cout << dist[i] << ' '; } }
入力
0
8 7
0 3
1 3
1 2
3 7
3 4
7 4
5 6
出力
0 2 3 1 2 -1 -1 2
BFS(色分け)
0から始まる数字で連結成分ごとに色分けする。
//0から始まる数字で色分けして配列で返す vector<int>bfs_graph_color(vector<set<int>>G) { int color = 0; int V = G.size(); vector<int>COLOR(V, INF); rep(start, V) { if (COLOR[start] == INF) { queue<int> que; COLOR[start] = color; que.push(start); while (!que.empty()) { int v = que.front(); que.pop(); for (auto nv : G[v]) { if (COLOR[nv] != INF)continue; COLOR[nv] = color; que.push(nv); } } color++; } } return COLOR; }
コード例
//0から始まる数字で色分けして配列で返す vector<int>bfs_graph_color(vector<set<int>>G) { int color = 0; int V = G.size(); vector<int>COLOR(V, INF); rep(start, V) { if (COLOR[start] == INF) { queue<int> que; COLOR[start] = color; que.push(start); while (!que.empty()) { int v = que.front(); que.pop(); for (auto nv : G[v]) { if (COLOR[nv] != INF)continue; COLOR[nv] = color; que.push(nv); } } color++; } } return COLOR; } signed main() { int V;//頂点数 int E;//辺の数 cin >> V >> E; vector<set<int>>G(V);//隣接リスト for (int i = 0; i < E; i++) { int a, b; cin >> a >> b; G[a].insert(b); G[b].insert(a); } vector<int>COLOR = bfs_graph_color(G); rep(i, V) { cout << COLOR[i] << ' '; } }
入力
8 7
0 3
1 3
1 2
3 7
3 4
7 4
5 6
出力
0 0 0 0 0 1 1 0