#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using ll = long long; using vi = vector; using vvi = vector; using vl = vector; using vvl = vector; using vb = vector; using vvb = vector; using vd = vector; using vs = vector; using pii = pair; using pll = pair; using pdd = pair; using vpii = vector; using vpll = vector; using vpdd = vector; const int inf = (1 << 30) - 1; const ll INF = 1LL << 60; //const int MOD = 1000000007; const int MOD = 998244353; struct SCC { using Edge = int; using SGraph = vector>; // input SGraph G, rG; // result vector> scc; vector cmp; SGraph dag; // constructor SCC(int N) : G(N), rG(N) {} // add edge void addedge(int u, int v) { G[u].push_back(v); rG[v].push_back(u); } // decomp vector seen; vector vs, rvs; void dfs(int v) { seen[v] = true; for (auto e : G[v]) if (!seen[e]) dfs(e); vs.push_back(v); } void rdfs(int v, int k) { seen[v] = true; cmp[v] = k; for (auto e : rG[v]) if (!seen[e]) rdfs(e, k); rvs.push_back(v); } // reconstruct set> newEdges; void reconstruct() { int N = (int)G.size(); int dV = (int)scc.size(); dag.assign(dV, vector()); newEdges.clear(); for (int i = 0; i < N; ++i) { int u = cmp[i]; for (auto e : G[i]) { int v = cmp[e]; if (u == v) continue; if (!newEdges.count({ u, v })) { dag[u].push_back(v); newEdges.insert({ u, v }); } } } } // main void solve() { // first dfs int N = (int)G.size(); seen.assign(N, false); vs.clear(); for (int v = 0; v < N; ++v) if (!seen[v]) dfs(v); // back dfs int k = 0; scc.clear(); cmp.assign(N, -1); seen.assign(N, false); for (int i = N - 1; i >= 0; --i) { if (!seen[vs[i]]) { rvs.clear(); rdfs(vs[i], k++); scc.push_back(rvs); } } reconstruct(); } }; int main() { int n; cin >> n; vi l(n), s(n); SCC scc(n); for (int i = 0; i < n; i++) { cin >> l[i] >> s[i]; s[i]--; if(s[i] != i) scc.addedge(s[i], i); } scc.solve(); vb visit(n, false); double ans = 0; for (int i = 0; i < scc.scc.size(); i++) { if (scc.scc[i].size() == 1) { int v = scc.scc[i][0]; if (visit[s[v]]) ans += l[v] / 2.0; else ans += l[v]; visit[v] = true; } else { double mi = inf; for (auto& v : scc.scc[i]) { ans += l[v] / 2.0; mi = min(mi, l[v] / 2.0); visit[v] = true; } ans += mi; } } cout << fixed << setprecision(1); cout << ans << endl; }