結果
| 問題 |
No.19 ステージの選択
|
| ユーザー |
|
| 提出日時 | 2016-03-29 20:35:11 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
AC
|
| 実行時間 | 2 ms / 5,000 ms |
| コード長 | 2,773 bytes |
| コンパイル時間 | 968 ms |
| コンパイル使用メモリ | 88,508 KB |
| 実行使用メモリ | 5,248 KB |
| 最終ジャッジ日時 | 2024-12-23 10:04:33 |
| 合計ジャッジ時間 | 1,888 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 24 |
ソースコード
#include <iostream>
#include <iomanip>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <climits>
using namespace std;
class UnionFind {
public:
UnionFind(int count) {
elements_.resize(count + 1, -1);
}
int Find(int num) {
if (elements_[num] < 0) {
return num;
}
else {
return Find(elements_[num]);
}
}
void Union(int num1, int num2) {
int find1 = Find(num1);
int find2 = Find(num2);
if (find1 == find2)
return;
if (elements_[find1] <= elements_[find2]) {
elements_[find1] += elements_[find2];
elements_[find2] = find1;
}
else {
elements_[find2] += elements_[find1];
elements_[find1] = find2;
}
}
unordered_map<int, vector<int>> GetSubsets() {
unordered_map<int, vector<int>> result;
for (int i = 1; i < elements_.size(); i++) {
int root = Find(i);
result[root].emplace_back(i);
}
return result;
}
private:
vector<int> elements_;
};
vector<int> difficulty;
int GetDifficulty(int stage) {
return difficulty[stage] * 10;
}
int main() {
int N;
cin >> N;
UnionFind uf(N);
vector<int> nodes(N + 1, -1);
difficulty.resize(N + 1, -1);
for (int i = 1; i <= N; i++) {
int L, S;
cin >> L >> S;
difficulty[i] = L;
if (i != S) {
nodes[i] = S;
uf.Union(i, S);
}
}
int ans = 0;
vector<bool> visited(N + 1, false);
vector<bool> closed_path(N + 1, false);
unordered_map<int, vector<int>> subsets = uf.GetSubsets();
for (auto pair : subsets) {
vector<int> closed_path_nodes;
int current = pair.second[0];
while (nodes[current] != -1) {
if (visited[current]) {
int closed_path_start = current;
do {
closed_path[current] = true;
closed_path_nodes.emplace_back(current);
current = nodes[current];
} while (current != closed_path_start);
break;
}
visited[current] = true;
current = nodes[current];
}
if (closed_path_nodes.empty()) {
for (auto stage : pair.second) {
if (nodes[stage] == -1) {
ans += GetDifficulty(stage);
}
else {
ans += GetDifficulty(stage) / 2;
}
}
}
else {
int min_cost = INT_MAX;
reverse(closed_path_nodes.begin(), closed_path_nodes.end());
for (int i = 0; i < closed_path_nodes.size(); i++) {
int cost = GetDifficulty(closed_path_nodes[i]);
int loop_count = 1;
while (loop_count < closed_path_nodes.size()) {
int index = (i + loop_count) % closed_path_nodes.size();
cost += GetDifficulty(closed_path_nodes[index]) / 2;
loop_count++;
}
min_cost = min(min_cost, cost);
}
for (auto stage : pair.second) {
if (!closed_path[stage]) {
min_cost += GetDifficulty(stage) / 2;
}
}
ans += min_cost;
}
}
cout << fixed << setprecision(1) << (double)ans / 10 << endl;
return 0;
}