Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Reputeless committed Nov 27, 2022
1 parent abfa5a0 commit 45e24d6
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 1 deletion.
107 changes: 107 additions & 0 deletions 021.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# 021 - Come Back in One Piece (★5)

## 解答

```cpp
#include <iostream>
#include <vector>
#include <algorithm> // std::reverse(), std::fill()

using Graph = std::vector<std::vector<int>>;

void DFS(const Graph& g, int from, std::vector<bool>& visited, std::vector<int>& results)
{
visited[from] = true;

for (const auto& to : g[from])
{
if (!visited[to])
{
DFS(g, to, visited, results);
}
}

// 帰りがけ順に頂点を記録
results.push_back(from);
}

void DFS2(const Graph& g, int from, long long& count, std::vector<bool>& visited)
{
visited[from] = true;

++count;

for (const auto& to : g[from])
{
if (!visited[to])
{
DFS2(g, to, count, visited);
}
}
}

int main()
{
// N 頂点, M 辺
int N, M;
std::cin >> N >> M;

// 入力されたグラフ
Graph g1(N);

// 辺の向きを反転したグラフ
Graph g2(N);

for (int i = 0; i < M; ++i)
{
int from, to;
std::cin >> from >> to;
--from;
--to;

g1[from].push_back(to);
g2[to].push_back(from);
}

// 頂点が訪問済みか記録する配列
std::vector<bool> visited(N);

// 帰りがけ順に頂点を記録する配列
std::vector<int> results;

for (int i = 0; i < N; ++i)
{
if (!visited[i])
{
DFS(g1, i, visited, results);
}
}

// 帰りがけ順が大きい頂点から処理するため並び順を反転
std::reverse(results.begin(), results.end());

// 次の探索のために、訪問済み頂点をリセット
std::fill(visited.begin(), visited.end(), false);

long long answer = 0;

for (int from : results)
{
if (visited[from])
{
continue;
}
long long count = 0;

// 行き止まりになるまでの頂点数を count に記録
DFS2(g2, from, count, visited);

// そのグループの頂点数から、answer に追加するペア数を求める
answer += (count * (count - 1) / 2);
}

// 解答を出力
std::cout << answer << '\n';
}
```
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ C++17 標準ライブラリの機能を優先して使い、競技プログラ
|:--:|--|:--:|:--:|--|
|[006](https://atcoder.jp/contests/typical90/tasks/typical90_f)|Smallest Subsequence|★5|[👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/006.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/006.cpp)|辞書順最小は前から貪欲法|
|[013](https://atcoder.jp/contests/typical90/tasks/typical90_m)|[Passing](./013.md)|★5|[👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/013.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/013.cpp)|各頂点への最短経路はダイクストラ|
|021| | | | |
|[021](https://atcoder.jp/contests/typical90/tasks/typical90_u)|[Come Back in One Piece](./021.md)|★5|[👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/021.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/021.cpp)|強連結成分分解(SCC)をしよう|
|[029](https://atcoder.jp/contests/typical90/tasks/typical90_ac)|[Long Bricks](./029.md)|★5|(1) [👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/029-01.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/029-01.cpp),[📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/029-02.cpp)<br>(2) [👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/029-02.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/029-03.cpp)|(解法 1) 「座標圧縮」で効率化<br>(解法 2) 区間に対する処理は「セグメント木」|
|030| | | | |
|[036](https://atcoder.jp/contests/typical90/tasks/typical90_aj)|[Max Manhattan Distance](./036.md)|★5|[👨‍🏫](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/036.jpg) / [📝](https://github.com/E869120/kyopro_educational_90/blob/main/sol/036.cpp)|マンハッタン距離は 45 度回転|
Expand Down

0 comments on commit 45e24d6

Please sign in to comment.