/*** author: yuji9511 ***/ #include // #include // using namespace atcoder; using namespace std; using ll = long long; using lpair = pair; using vll = vector; const ll MOD = 1e9+7; const ll INF = 1e18; #define rep(i,m,n) for(ll i=(m);i<(n);i++) #define rrep(i,m,n) for(ll i=(m);i>=(n);i--) #define printa(x,n) for(ll i=0;i void print(H&& h, T&&... t){cout<(t)...);} using UnWeightedGraph = vector; template< typename G > struct SCC { const G &g; UnWeightedGraph gg, rg; vll comp, order, used; SCC(G &g) : g(g), gg(g.size()), rg(g.size()), comp(g.size(), -1), used(g.size()) { for(int i = 0; i < g.size(); i++) { for(auto e : g[i]) { gg[i].emplace_back((int) e); rg[(int) e].emplace_back(i); } } } int operator[](int k) { return comp[k]; } void dfs(int idx) { if(used[idx]) return; used[idx] = true; for(int to : gg[idx]) dfs(to); order.push_back(idx); } void rdfs(int idx, int cnt) { if(comp[idx] != -1) return; comp[idx] = cnt; for(int to : rg[idx]) rdfs(to, cnt); } void build(UnWeightedGraph &t) { for(int i = 0; i < gg.size(); i++) dfs(i); reverse(begin(order), end(order)); int ptr = 0; for(int i : order) if(comp[i] == -1) rdfs(i, ptr), ptr++; t.resize(ptr); for(int i = 0; i < g.size(); i++) { for(auto &to : g[i]) { int x = comp[i], y = comp[to]; if(x == y) continue; t[x].push_back(y); } } } }; struct UnionFind { private: ll N; vector parent; vector num; vector diff_weight; public: UnionFind(ll n){ N = n; parent.resize(N); iota(parent.begin(), parent.end(), 0); num.assign(N, 1); diff_weight.assign(N, 0); } ll root(ll x){ if(x == parent[x]){ return x; }else{ ll r = root(parent[x]); diff_weight[x] += diff_weight[parent[x]]; return parent[x] = r; } } void unite(ll a, ll b, ll w = 0){ w += weight(a); w -= weight(b); a = root(a); b = root(b); if(a == b) return; parent[b] = a; ll sum = num[a] + num[b]; num[a] = sum; num[b] = sum; diff_weight[b] = w; } bool same(ll a, ll b){ return root(a) == root(b);} ll sz(ll x){ return num[root(x)];} ll weight(ll x){ root(x); return diff_weight[x]; } ll diff(ll a, ll b){ return weight(b) - weight(a); } }; void solve(){ ll N; cin >> N; vll L(N), S(N); UnWeightedGraph g(N); UnionFind uf(N); map loop; rep(i,0,N){ cin >> L[i] >> S[i]; S[i]--; g[S[i]].push_back(i); uf.unite(i, S[i]); if(i == S[i]) loop[i] = true; } UnWeightedGraph tree; SCC scc(g); scc.build(tree); double ans = 0.0; vll min_val(N+1, INF); vll cnt(N+1, 0); rep(i,0,N) cnt[scc[i]]++; rep(i,0,N){ if(cnt[scc[i]] == 1 && loop[i] == false) continue; min_val[scc[i]] = min(min_val[scc[i]], L[i]); } rep(i,0,N){ ans += (double) L[i] / 2.0; } rep(i,0,N){ if(min_val[i] != INF){ ans +=(double) min_val[i] / 2.0; } } printf("%.1f\n", ans); } int main(){ cin.tie(0); ios::sync_with_stdio(false); solve(); }