結果
| 問題 |
No.19 ステージの選択
|
| ユーザー |
|
| 提出日時 | 2017-06-17 15:57:43 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 2 ms / 5,000 ms |
| コード長 | 5,363 bytes |
| コンパイル時間 | 1,669 ms |
| コンパイル使用メモリ | 178,488 KB |
| 実行使用メモリ | 5,248 KB |
| 最終ジャッジ日時 | 2024-12-23 10:07:08 |
| 合計ジャッジ時間 | 2,423 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 24 |
ソースコード
#include <bits/stdc++.h>
#define FOR(i, a, b) for (ll i = (a); i < (b); i++)
#define RFOR(i, a, b) for (ll i = (b)-1; i >= (a); i--)
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define rep1(i, n) for (ll i = 1; i <= (n); i++)
#define rrep(i, n) for (ll i = (n)-1; i >= 0; i--)
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
#define show(x) cout << #x << " = " << x << endl
#define chmin(x, y) x = min(x, y)
#define chmax(x, y) x = max(x, y)
#define pii pair<int, int>
#define vi vector<int>
using namespace std;
template <class S, class T>
ostream& operator<<(ostream& o, const pair<S, T>& p)
{
return o << "(" << p.first << "," << p.second << ")";
}
template <class T>
ostream& operator<<(ostream& o, const vector<T>& vc)
{
o << "sz = " << vc.size() << endl
<< "[";
for (const T& v : vc)
o << v << ",";
o << "]";
return o;
}
using ll = long long;
constexpr ll MOD = 1000000007;
// Just stands for connections
class LinkList
{
public:
LinkList(const std::size_t v) : m_v{v}
{
m_table.resize(v);
m_reversed_table.resize(v);
}
void addEdge(const std::size_t from, const std::size_t to)
{
m_e++;
m_table[from].push_back(to);
m_reversed_table[to].push_back(from);
}
void TopologocalSort(std::vector<std::size_t>& srt) const
{
srt.clear();
std::vector<bool> used(m_v, false);
for (std::size_t i = 0; i < m_v; i++) {
dfs_topo(i, used, srt);
}
std::reverse(srt.begin(), srt.end());
}
std::size_t SCC(std::vector<std::size_t>& cmp) const
{
assert(cmp.size() == m_v);
for (std::size_t i = 0; i < m_v; i++) {
cmp[i] = 0;
}
std::vector<std::size_t> st;
std::vector<bool> used(m_v, false);
for (std::size_t i = 0; i < m_v; i++) {
if (not used[i]) {
dfs1_scc(i, st, used);
}
}
for (std::size_t i = 0; i < m_v; i++) {
used[i] = false;
}
std::size_t comp = 0;
for (std::size_t i = 0; i < st.size(); i++) {
const std::size_t s = st[st.size() - i - 1];
if (not used[s]) {
dfs2_scc(s, comp++, cmp, used);
}
}
return comp;
}
std::size_t getV() const
{
return m_v;
}
std::size_t getE() const
{
return m_e;
}
const std::vector<std::vector<std::size_t>>& getEdge() const
{
return m_table;
}
std::vector<std::vector<std::size_t>>& getEdge()
{
return m_table;
}
const std::vector<std::vector<std::size_t>>& getReversedEdge() const
{
return m_reversed_table;
}
std::vector<std::vector<std::size_t>>& getReversedEdge()
{
return m_reversed_table;
}
private:
void dfs_topo(const std::size_t s, std::vector<bool>& used, std::vector<std::size_t>& srt) const
{
assert(s < m_v);
assert(used.size() == m_v);
if (not used[s]) {
used[s] = true;
for (const std::size_t to : m_table[s]) {
dfs_topo(to, used, srt);
}
srt.push_back(s);
}
}
void dfs1_scc(const std::size_t s, std::vector<std::size_t>& st, std::vector<bool>& used) const
{
assert(s < m_v);
assert(used.size() == m_v);
used[s] = true;
for (const std::size_t to : m_table[s]) {
if (not used[to]) {
dfs1_scc(to, st, used);
}
}
st.push_back(s);
}
void dfs2_scc(const std::size_t s, const std::size_t index, std::vector<std::size_t>& cmp, std::vector<bool>& used) const
{
assert(s < m_v);
assert(index < m_v);
assert(cmp.size() == m_v);
cmp[s] = index;
used[s] = true;
for (const std::size_t to : m_reversed_table[s]) {
if (not used[to]) {
dfs2_scc(to, index, cmp, used);
}
}
};
const std::size_t m_v;
std::size_t m_e;
std::vector<std::vector<std::size_t>> m_table;
std::vector<std::vector<std::size_t>> m_reversed_table;
};
void dfs(const LinkList& g, const std::size_t pos, vector<bool>& checked)
{
checked[pos] = true;
for (const std::size_t to : g.getEdge()[pos]) {
if (not checked[to]) {
dfs(g, to, checked);
}
}
}
int main()
{
std::size_t n;
cin >> n;
vector<int> level(n);
int sum = 0;
LinkList g(n);
rep(i, n)
{
int l, par;
cin >> l >> par;
sum += l;
level[i] = l;
par--;
g.addEdge(par, i);
}
vector<std::size_t> comp(n);
const std::size_t size = g.SCC(comp);
constexpr int INF = numeric_limits<int>::max() / 100;
vector<bool> checked(n, false);
for (int c = 0; c < size; c++) {
int mini = INF;
int pos = 0;
for (int i = 0; i < n; i++) {
if (comp[i] == c and (not checked[i])) {
pos = i;
mini = min(mini, level[i]);
}
}
if (mini != INF) {
dfs(g, pos, checked);
sum += mini;
}
}
cout << fixed << setprecision(1) << sum * 1.0 / 2 << endl;
return 0;
}