#include using namespace std; #define REP(i,a,b) for(i=a;i'9')break;*x=(*x)*10+k-'0';}if(m)(*x)=-(*x);} void reader(int *x, int *y){reader(x);reader(y);} void reader(int *x, int *y, int *z){reader(x);reader(y);reader(z);} void reader(ll *x){int k,m=0;*x=0;for(;;){mygc(k);if(k=='-'){m=1;break;}if('0'<=k&&k<='9'){*x=k-'0';break;}}for(;;){mygc(k);if(k<'0'||k>'9')break;*x=(*x)*10+k-'0';}if(m)(*x)=-(*x);} int reader(char c[]){int i,s=0;for(;;){mygc(i);if(i!=' '&&i!='\n'&&i!='\r'&&i!='\t'&&i!=EOF) break;}c[s++]=i;for(;;){mygc(i);if(i==' '||i=='\n'||i=='\r'||i=='\t'||i==EOF) break;c[s++]=i;}c[s]='\0';return s;} void writer(int x, char c){int s=0,m=0;char f[10];if(x<0)m=1,x=-x;while(x)f[s++]=x%10,x/=10;if(!s)f[s++]=0;if(m)mypc('-');while(s--)mypc(f[s]+'0');mypc(c);} void writer(ll x, char c){int s=0,m=0;char f[20];if(x<0)m=1,x=-x;while(x)f[s++]=x%10,x/=10;if(!s)f[s++]=0;if(m)mypc('-');while(s--)mypc(f[s]+'0');mypc(c);} void writer(const char c[]){int i;for(i=0;c[i]!='\0';i++)mypc(c[i]);} void* setDirectEdge(int N, int M, int A[], int B[], int **es, int ***edge, void *workMemory){int i;*es=(int*)workMemory;*edge=(int**)((*es)+N);(*edge)[0]=(int*)((*edge)+N);rep(i,N)(*es)[i]=0;rep(i,M)(*es)[A[i]]++;REP(i,1,N)(*edge)[i]=(*edge)[i-1]+(*es)[i-1];workMemory=(void*)((*edge)[N-1]+(*es)[N-1]);rep(i,N)(*es)[i]=0;rep(i,M)(*edge)[A[i]][(*es)[A[i]]++]=B[i];return workMemory;} void* setUndirectEdge(int N, int M, int A[], int B[], int **es, int ***edge, void *workMemory){int i;*es=(int*)workMemory;*edge=(int**)((*es)+N);(*edge)[0]=(int*)((*edge)+N);rep(i,N)(*es)[i]=0;rep(i,M)(*es)[A[i]]++,(*es)[B[i]]++;REP(i,1,N)(*edge)[i]=(*edge)[i-1]+(*es)[i-1];workMemory=(void*)((*edge)[N-1]+(*es)[N-1]);rep(i,N)(*es)[i]=0;rep(i,M)(*edge)[A[i]][(*es)[A[i]]++]=B[i],(*edge)[B[i]][(*es)[B[i]]++]=A[i];return workMemory;} void* getReverseGraph(int N, int *es, int **edge, int **r_es, int ***r_edge, void *workMemory){int i,j,k;*r_es=(int*)workMemory;*r_edge=(int**)((*r_es)+N);(*r_edge)[0]=(int*)((*r_edge)+N);rep(i,N)(*r_es)[i] = 0;rep(i,N)rep(j,es[i])(*r_es)[edge[i][j]]++;REP(i,1,N)(*r_edge)[i]=(*r_edge)[i-1]+(*r_es)[i-1];workMemory=(void*)((*r_edge)[N-1]+(*r_es)[N-1]);rep(i,N)(*r_es)[i]=0;rep(i,N)rep(j,es[i])k=edge[i][j],(*r_edge)[k][(*r_es)[k]++]=i;return workMemory;} void getDepthOfTreeDFS(int node, int bef, int *depth, int *es, int **edge){int i,k;rep(i,es[node]){k=edge[node][i];if(bef==k)continue;depth[k]=depth[node] + 1;getDepthOfTreeDFS(k, node, depth, es, edge);}} void* getDepthOfTree(int N, int root, int *es, int **edge, int **depth, void *workMemory){*depth=(int*)workMemory;workMemory=(void*)((*depth)+N);(*depth)[root]=0;getDepthOfTreeDFS(root,-1,*depth,es,edge);return workMemory;} template void doublingRMQBuild(T arr[], int n, int res[]){int i,k,h;rep(i,n)res[i]=i;for(k=1;;k++){h=(1<<(k-1));if(h>=n)break;rep(i,n){res[n*k+i]=res[n*(k-1)+i];if(i+harr[res[n*(k-1)+i+h]])res[n*k+i]=res[n*(k-1)+i+h];}}} template void* doublingRMQBuild(T arr[], int n, int **res, void *workMemory){int i,k,h;*res=(int*)workMemory;rep(i,n)(*res)[i]=i;for(k=1;;k++){h=(1<<(k-1));if(h>=n)break;rep(i,n){(*res)[n*k+i]=(*res)[n*(k-1)+i];if(i+harr[(*res)[n*(k-1)+i+h]])(*res)[n*k+i]=(*res)[n*(k-1)+i+h];}}return (void*)((*res)+n*k);} template int doublingRMQQuery(T arr[], int n, int rmq[], int a, int b){int d,w=b-a+1,A,B;for(d=0;(1<<(d+1))<=w;d++);A=rmq[n*d+a];B=rmq[n*d+b-(1<arr[B]?B:A;} struct LCA{ int *depth, *vs, *id, *rmq, N, *es, **edge; void dfs(int node, int bef, int dep, int *num){int i,k;id[node]=*num;vs[*num]=node;depth[(*num)++]=dep;rep(i,es[node]){k=edge[node][i];if(k==bef)continue;dfs(k,node,dep+1,num);vs[*num]=node;depth[(*num)++]=dep;}} void* init(int N_, int root, int *es_, int **edge_, void *workMemory){int m=0;N=N_;es=es_;edge=edge_;depth=(int*)workMemory;vs=depth+2*N-1;id=vs+2*N-1;dfs(root,-1,0,&m);return doublingRMQBuild(depth,2*N-1,&rmq,(void*)(id+N));} int get(int a, int b){return vs[doublingRMQQuery(depth, 2*N-1, rmq, min(id[a],id[b]), max(id[a],id[b]))];} int getDepth(int a, int b){return depth[doublingRMQQuery(depth,2*N-1,rmq,min(id[a],id[b]),max(id[a],id[b]))];} }; int StronglyConnectedComponentsDFS(int *es, int **edge, int num[], int st, int mx){ int i,j; num[st]=-2; rep(i,es[st]) { j=edge[st][i]; if(num[j]==-1) mx=StronglyConnectedComponentsDFS(es,edge,num,j,mx); } num[st]=mx; return mx+1; } int StronglyConnectedComponents(int N, int *es, int **edge, int res[], void *workMemory){ int i, j, k, ret=0; int *r_es, **r_edge; int *st, st_size, *num, *nrv; workMemory = getReverseGraph(N, es, edge, &r_es, &r_edge, workMemory); st = (int*) workMemory; num = st+N; nrv = num + N; rep(i,N) res[i] = num[i] = -1; k = 0; rep(i,N) if(num[i]==-1) k = StronglyConnectedComponentsDFS(es,edge,num,i,k); rep(i,N) nrv[num[i]] = i; for(k=N-1;k>=0;k--) { i=nrv[k]; if(res[i]>=0)continue; res[i]=ret; st_size=0; st[st_size++]=i; while(st_size){ i=st[--st_size]; rep(j,r_es[i]) if(res[r_edge[i][j]]==-1) res[r_edge[i][j]]=ret, st[st_size++]=r_edge[i][j]; } ret++; } return ret; } int N; int A[222], B[222], L[222]; int com[222], deg[222], mn[222]; int main(){ int i, j, k, nn; int res; int *es, **edge; void *mem = malloc(10000000); reader(&N); rep(i,N) reader(L+i,A+i), A[i]--, B[i]=i; mem = setDirectEdge(N, N, A, B, &es, &edge, mem); nn = StronglyConnectedComponents(N, es, edge, com, mem); res = 0; rep(i,N) res += L[i]; rep(i,N) if(com[A[i]] != com[B[i]]) deg[com[B[i]]]++; rep(i,nn) mn[i] = 10000; rep(i,N) mn[com[i]] = min(mn[com[i]], L[i]); rep(i,nn) if(!deg[i]) res += mn[i]; printf("%.1f\n",res/2.0); return 0; }