The 10th Zhejiang Provincial Collegiate Programming Contest Solution

来源:互联网 发布:mac驱动精灵怎么安装 编辑:程序博客网 时间:2024/05/17 06:10


 

The 10th Zhejiang Provincial Collegiate 

Programming Contest

Solution

Problem A: Applications

Problem B: BreakStandard Weight

Problem C: CalculatePrime S

Problem D: Densityof Power Network

Problem E: EggPainting

Problem F: Friends

Problem G: Give MeYour Hand

Problem H: Hardto Play

Problem I: In7-bit

Problem J: JavaBeans

Problem K: KindergartenElection

June 3rd,2013 by chlxyd

 ZOJ 3705~3715

Problem A: Applications

给出一个积分方式,问每个人最后的分数并排序。

 

Solution

Tag:模拟

按照题目做就可以了,不是很难。

/* * Author:  chlxyd * Created Time:  2013/5/29 15:38:37 * File Name: A.CPP */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>using namespace std;const double eps(1e-11);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define sz(v) ((int)(v).size())#define rep(i, n) for (int i = 0; i < (n); ++i)#define repf(i, a, b) for (int i = (a); i <= (b); ++i)#define repd(i, a, b) for (int i = (a); i >= (b); --i)#define clrs( x , y ) memset( x , y , sizeof(x) )int sgn(double x) {    return (x > eps) - (x < -eps);}struct node {    string name;    double val;    node (string _name = "", double _val = 0.0) : name(_name), val(_val){    }    bool operator < (const node &b) const {        if (sgn(val - b.val) != 0) return val > b.val;        else return name < b.name;    }};int n, m;set<int> mao, S, pr;map<string, int> team;vector<node> peo;node getPon() {    string name, tm, sex;    vector<int> c;    double res = 0;    int pn, cn;    cin >> name >> tm >> sex >> pn >> cn;    //cout << name << " " << tm << " " << sex << endl;    if (sex[0] == 'F') res += 33;    if (team.count(tm) == 1) {        res += team[tm];    }    rep (i, pn) {        int x;        scanf("%d", &x);        if (mao.find(x) != mao.end()) {            res += 2.5;        }        else if (S.find(x) != S.end()) {            res += 1.5;        }        else if (pr.find(x) != pr.end()) {            res += 1;        }        else {            res += 0.3;        }    }    rep (i, cn) {        int x;        scanf("%d", &x);        c.push_back(x);    }    sort(c.begin(), c.end());    reverse(c.begin(), c.end());    if (sz(c) >= 3) {        res += max(0.0, (c[2] - 1200) / 100.0) * 1.5;    }    return node(name, res);}void init() {    scanf("%d%d", &n, &m);    int mn, sn, tn;    mao.clear();    S.clear();    scanf("%d", &mn);    rep (i, mn) {        int x;        scanf("%d", &x);        mao.insert(x);    }     scanf("%d", &sn);    rep (i, sn) {        int x;        scanf("%d", &x);        S.insert(x);    }    scanf("%d", &tn);    team.clear();    rep (i, tn) {        string name;        int pr;        cin >> name >> pr;        if (pr == 1) pr = 36;        else if (pr == 2) pr = 27;        else if (pr == 3) pr = 18;        else pr = 0;        team[name] = pr;    }        peo.clear();    rep (i, n) {        node res;        res = getPon();        peo.push_back(res);    }}int v[20000 + 10];void getPr() {    int lim = 20000 + 10;    memset(v, 0, sizeof(v));    pr.clear();    for (int i = 2; i < lim; i++) {        if (!v[i]) {            pr.insert(i);            for (int j = i + i; j < lim; j += i) {                v[j] = 1;            }        }    }}void gao() {    sort(peo.begin(), peo.end());    rep (i, m) {        cout << peo[i].name;        printf(" %.3f\n", peo[i].val);    }}int main(){    int T;    getPr();    scanf("%d", &T) ;    while (T--) {        init();        gao();    }    return 0;}

 

Problem B: BreakStandard Weight

 

Solution

Tag:暴力

 

/* * Author:  chlxyd * Created Time:  2013/5/29 13:53:33 * File Name: B.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>using namespace std;const double eps(1e-8);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define sz(v) ((int)(v).size())#define rep(i, n) for (int i = 0; i < (n); ++i)#define repf(i, a, b) for (int i = (a); i <= (b); ++i)#define repd(i, a, b) for (int i = (a); i >= (b); --i)#define clrs( x , y ) memset( x , y , sizeof(x) )int gao(int xx, int yy) {    int x, y, z;    int res = 0;    repf (i, 1, xx - 1) {        vector<int> a;        x = i;        z = xx - i;        y = yy;        repf (ii, -1, 1)            repf (jj, -1, 1)                repf (kk, -1, 1) {                    a.push_back(ii * x + jj * y + kk * z);                }        sort(a.begin(), a.end());        a.erase(unique(a.begin(), a.end()), a.end());        int h = 0;        rep (j, sz(a))            if (a[j] > 0) {                h = sz(a) - j;                break;            }        res = max(h, res);    }    return res;}int main(){    int T;    scanf("%d", &T);    while (T--) {        int x, y;        scanf("%d%d", &x, &y);        int res = 0;        res = max(res, gao(x, y));        res = max(res, gao(y, x));        printf("%d\n", res);    }    return 0;}

Problem C: CalculatePrime S

S[n]是1到n中不包含连续数的子集的个数,如果s[n]与s[1]~s[n-1]均互斥,那么定义s[n]为素数,问最小的s[n]使s[n]是x的倍数,且s[n]不小于第k个素数。

 

Solution

Tag:数论

首先可以看出s[n]是斐波拉契数列,根据斐波拉契数列的性质,s[a]为质数,那么a为质数,即,找到第k个质数做下标,f[k]即是下界,那么对于x,斐波拉契数列mod x的结果一定构成一个循环,算出循环里有多少个0,即有多少数能被x整除,即可以通过循环节找到答案的下标位置,设为g,现在就是求(f[g]/x)%M的值。可以也按照循环节的方式来做,不过会T,有一个性质是a / b % m = a % (m * b) / b , 这样就可以先用矩阵乘法算出上面的然后再除下面了。

 

/* * Author:  xioumu * Created Time:  2013/5/29 17:47:57 * File Name: C.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>using namespace std;const double eps(1e-8);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define sz(v) ((int)(v).size())#define rep(i, n) for (lint i = 0; i < (n); ++i)#define repf(i, a, b) for (lint i = (a); i <= (b); ++i)#define repd(i, a, b) for (lint i = (a); i >= (b); --i)#define clrs( x , y ) memset( x , y , sizeof(x) )const lint maxa = 3;const lint lim = 20000000;lint mod;vector<lint> pri;bool v[lim];lint K, X, M;struct matrix {    lint ar[maxa][maxa];    lint n, m ; // n * m; 0 ~ n - 1, 0 ~ m - 1;    matrix(int _n = 0, int _m = 0) : n(_n), m(_m) {        memset(ar, 0, sizeof(ar));    }    void clear() {        rep (i, n)            rep (j, m)                ar[i][j] = 0;    }    void set_one() {        rep (i, n)            rep (j, m)                ar[i][j] = 0;        rep (i, min(n, m))            ar[i][i] = 1;    }    void output() {        printf("%lld %lld\n", n, m);        rep(i, n) {            rep(j, m)                printf("%lld ", ar[i][j]);            printf("\n");        }        printf("\n");    }};matrix operator * (const matrix &a, const matrix &b) {    matrix c;    if(a.m != b.n) printf("a.m != b.n\n");    c.clear();    c.n = a.n;    c.m = b.m;    rep (i, a.n)          rep (j, b.m)          rep (k, a.m) {            c.ar[i][j] += a.ar[i][k] * b.ar[k][j];   //mod            c.ar[i][j] %= mod;        }    return c;}void getPr() {    pri.clear();    memset(v, 0, sizeof(v));    for (lint i = 2; i < lim; i++) {        if (!v[i]) {            pri.push_back(i);        }        else if (i == 4)            pri.push_back(2);        for (lint j = 0; (lint)i * pri[j] < lim; j++) {            v[i * pri[j]] = true;            if (i % pri[j] == 0) {                break;            }        }    }    pri[2] = 4;    //printf("=%d\n", pri[1]);}matrix pow(matrix a, lint b) {    matrix res;    res.n = res.m = 2;    res.set_one();    //printf("b: %lld\n", b);    while (b != 0) {        //cout << "BB:  " << b << endl;        if (b & 1) {            res = a * res;        }        a = a * a;        b >>= 1;    }    //res.output();    return res;}lint gao(lint be) {    //printf("be : %d\n", be);    matrix a, p;    p.clear();    p.n = p.m = 2;    p.ar[0][0] = p.ar[0][1] = p.ar[1][0] = 1;    p.ar[1][1] = 0;    p = pow(p, be - 1);//p.output();     a.clear();    a.n = 2, a.m = 1;    a.ar[0][0] = 1;    a.ar[1][0] = 1;        a = p * a;    lint now1 = a.ar[0][0], now2 = a.ar[1][0];    //printf("%lld %lld\n", now1, now2);    rep (i, 20000) {        //printf("=%lld\n", now1);        if (now2 % X == 0) return now2 / X;        lint now3 = (now1 + now2) % mod;        now2 = now1;        now1 = now3;        //printf("%lld\n", now1);    }     return -1;}int main(){    getPr();    lint T;    scanf("%lld", &T);    while (T--) {        scanf("%lld%lld%lld", &K, &X, &M);        mod = X * M;        //printf("%lld\n", pri[K]);        lint ans = gao(pri[K]); //题目说 not less than the Kth, 觉得应该是K - 1, 也许标程错了?        printf("%lld\n", ans % M);    }    return 0;}

Problem D: Densityof Power Network

 

Solution

Tag:图论


/* * Author:  chlxyd * Created Time:  2013/5/29 14:07:51 * File Name: D.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>using namespace std;const double eps(1e-8);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define sz(v) ((int)(v).size())#define rep(i, n) for (int i = 0; i < (n); ++i)#define repf(i, a, b) for (int i = (a); i <= (b); ++i)#define repd(i, a, b) for (int i = (a); i >= (b); --i)#define clrs( x , y ) memset( x , y , sizeof(x) )const int maxn = 507;bool a[maxn][maxn];int x[maxn], y[maxn];int n, m;int main(){    int T;    scanf("%d", &T);     memset(a, 0, sizeof(a));    while (T--) {        scanf("%d%d", &n, &m);        int ans = 0;        rep (i, m) {            scanf("%d", &x[i]);        }        rep (i, m) {            scanf("%d", &y[i]);        }        rep (i, m) {            if (!a[x[i]][y[i]])                ans++;            a[x[i]][y[i]] = a[y[i]][x[i]] = true;        }        rep (i, m)            a[x[i]][y[i]] = a[y[i]][x[i]] = false;        printf("%.3f\n", ans * 1.0 / n);    }    return 0;}

Problem E: EggPainting

Unknown

 

Solution

Tagunknown

Unknown

 

Problem F: Friends

给很多人和朋友关系,两个人如果公共朋友大于等于k那么他们会变成朋友,问最后会新增多少对朋友关系。

 

Solution

Tag:图论

可以用类似spfa的方法对于每一条新增的边计算由它可以生成的新边,加入队列中。复杂度O(n3)。

 

/* * Author:  chlxyd * Created Time:  2013/5/29 14:14:47 * File Name: F.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>using namespace std;const double eps(1e-8);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define sz(v) ((int)(v).size())#define rep(i, n) for (int i = 0; i < (n); ++i)#define repf(i, a, b) for (int i = (a); i <= (b); ++i)#define repd(i, a, b) for (int i = (a); i >= (b); --i)#define clrs( x , y ) memset( x , y , sizeof(x) )int T ;int n , m , K ;int f[200][200] ;int num[200][200] ;queue<pair<int,int> > q ;int main(){    scanf("%d" , &T ) ;    repf( t , 1 , T  ) {        while (!q.empty()) q.pop() ;        clr(num) ; clr(f) ;        scanf("%d %d %d" , &n , &m , &K ) ;        repf( i , 1 , m ) {            int a , b ;            scanf("%d %d" , &a , &b ) ;            a ++ ; b ++ ;            f[a][b] = f[b][a] = true ;        }        repf( k , 1 , n )             repf( i , 1 , n )                 repf( j , i + 1 , n ) {                    if ( f[i][k] && f[k][j] ) {                        num[i][j] ++ ; num[j][i] ++ ;                    }                }        repf( i , 1 , n )             repf( j , i + 1 , n ) {                if ( num[i][j] >= K && !f[i][j] ) {                    f[i][j] = f[j][i] = true ;                    q.push( make_pair(i,j) ) ;                }            }        int ans = 0 ;        while ( !q.empty() ) {            int a = q.front().first , b = q.front().second ;            //cout<<a<<" "<<b<<endl;            q.pop() ; ans ++ ;            repf( i , 1 , n ) {                if ( f[i][a] ) {                    if ( i == b ) continue ;                    num[i][b] ++ ; num[b][i] ++ ;                    if ( num[i][b] >= K && !f[i][b] ) {                        f[i][b] = true ; f[b][i] = true ;                        q.push(make_pair(i,b)) ;                    }                }            }            swap( a , b ) ;            repf( i , 1 , n ) {                if ( f[i][a] ) {                    if ( i == b ) continue ;                    num[i][b] ++ ; num[b][i] ++ ;                    if ( num[i][b] >= K && !f[i][b] ) {                        f[i][b] = true ; f[b][i] = true ;                        q.push(make_pair(i,b)) ;                    }                }            }        }        printf("%d\n" , ans ) ;    }}

Problem G: GiveMe Your Hand

寝室最开始是空的,寝室有n个人,其中A和B比较特殊,其余是酱油,A如果在寝室呆着超过了T分钟,那么A就开始打游戏,这时如果B在里面,那么A就失去一只玩具手,然后又可以再呆T分钟,A有M只玩具手,给很多时间,每个时间发生一个事件,事件包括一个人进或者一个人出,进或者出或者谁进谁出都是随机的,问A最后失去的玩具手的期望。

 

Solution

TagDP

状态:f[i][S][T][m]表示在事件i,A和B是否在寝室的状态为S(0~3),A已经在寝室呆了T分钟,还剩m只玩具手的概率,转移见代码。

 

/* * Author:  chlxyd * Created Time:  2013/5/29 16:45:55 * File Name: G.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>using namespace std;const double eps(1e-8);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define sz(v) ((int)(v).size())#define rep(i, n) for (int i = 0; i < (n); ++i)#define repf(i, a, b) for (int i = (a); i <= (b); ++i)#define repd(i, a, b) for (int i = (a); i >= (b); --i)#define clrs( x , y ) memset( x , y , sizeof(x) )int T , num , n , m ;double p[110][4][110][110] ;//int flag[110][4][110][110] ;int t1[200] ;int minu( int a , int b ) {    if ( a > b ) return a - b ;    return 0 ;}int main(){    int T_T ;    scanf("%d" , &T_T ) ;    //freopen("G.out","w",stdout);    repf( tt , 1 , T_T  ) {        scanf("%d %d %d %d" , &T , &num , &m , &n ) ;        repf( i , 0 , num + 1 )             repf( j , 0 , 3 )                 repf( k , 0 , T )                     repf( l , 0 , m )                        p[i][j][k][l] = 0 ;        clr(t1) ;        p[0][0][0][m] = 1.0 ;        repf( i , 1 , num + 1 ) {            bool flag = true ;            if ( i != num + 1 )                 scanf("%d" , &t1[i] ) ;            else {                flag = false ;                t1[i] = 1440 ;            }            if ( t1[i-1] == 1440 ) continue ;            int t = t1[i] - t1[i-1] ;            //cout<<"task"<<i<<endl;            //cout<<t<<endl;            double now = 0 ;            //00            repf( j , 0 , m ) {                now = p[i-1][0][0][j] ;                p[i][1][0][j] += now / n ;                p[i][2][0][j] += now / n ;                p[i][0][0][j] += now * ( n - 2 ) / n ;            }            //01            repf( j , 0 , m ) {                now = p[i-1][1][0][j] ;                p[i][3][0][j] += now / n ;                p[i][1][0][j] += now * ( n - 2 ) / n ;                p[i][0][0][j] += now / n ;            }            //10            repf( j , 0 , T )                repf( k , 0 , m ) {                    now = p[i-1][2][j][k] ;                    if ( flag )                         p[i][3][(j+t>=T)?0:(j+t)][minu(k,j+t>=T)] += now / n ;                    else p[i][2][min(T,j+t)][k] += now / n ;                    p[i][0][0][k] += now / n ;                    p[i][2][min(T,j+t)][k] += now * ( n - 2 ) / n ;                }            //11            repf( j , 0 , T )                repf( k , 0 , m ) {                    now = p[i-1][3][j][k] ;                    int nt = ( j + t ) % T ;                    int nk = minu( k , ( j + t ) / T ) ;                    p[i][1][0][nk] += now / n ;                    p[i][2][nt][nk] += now / n ;                    p[i][3][nt][nk] += now * ( n - 2 ) / n ;                }            if ( t1[i] == 1440 ) {                num = i ;                break ;            }        }        //cout<<p[3][3][0][m-1]<<endl;        double ans = 0 ;        repf( i , 0 , 3 )             repf( j , 0 , T )                repf( k , 0 , m )                     ans += p[num][i][j][k] * k ;        printf("%.6lf\n" , ans ) ;    } }

Problem H: Hardto Play

 

Solution

Tag:贪心

 

/* * Author:  chlxyd * Created Time:  2013/5/29 13:44:36 * File Name: H.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>using namespace std;const double eps(1e-8);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define sz(v) ((int)(v).size())#define rep(i, n) for (long long i = 0; i < (n); ++i)#define repf(i, a, b) for (long long i = (a); i <= (b); ++i)#define repd(i, a, b) for (long long i = (a); i >= (b); --i)#define clrs( x , y ) memset( x , y , sizeof(x) )long long cal( long long p , long long n , long long val ) {    return val * p * 2 * n + val * ( n - 1 ) * n ;}long long T ;long long a , b , c ;int main(){    scanf("%lld" , &T ) ;    repf( t , 1 , T ) {        scanf("%lld %lld %lld" , &a , &b , &c ) ;        long long have = a * 300 + b * 100 + c * 50 ;        //cout<<cal(a+b,c,50)<<endl;        long long minn = cal( 0 , a , 300 ) + cal( a , b , 100 ) + cal( a + b , c , 50 ) ;        long long maxx = cal( 0 , c , 50 ) + cal( c , b , 100 ) + cal( b + c , a , 300 ) ;        printf("%lld %lld\n" , minn + have , maxx + have ) ;    }}

Problem I: In7-bit

给出一种加密方法,按照所给方法对一段文本加密。

 

Solution

Tag:模拟

按照题目要求做即可。

 

/* * Author:  chlxyd * Created Time:  2013/5/29 14:39:59 * File Name: I.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>using namespace std;const double eps(1e-8);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define sz(v) ((int)(v).size())#define rep(i, n) for (int i = 0; i < (n); ++i)#define repf(i, a, b) for (int i = (a); i <= (b); ++i)#define repd(i, a, b) for (int i = (a); i >= (b); --i)#define clrs( x , y ) memset( x , y , sizeof(x) )const int maxn = 3000000 + 100;char s[maxn];vector<int> a;void myput(int w) {    a.clear();    while (w != 0) {        a.push_back(w % 2);        w >>= 1;        //printf("%d\n", a[sz(a) - 1]);    }    if (sz(a) == 0)        a.push_back(0);    for (int i = 0; i < sz(a); i += 7) {        int res = 0;        if (i + 7 >= sz(a)) {            res = 0;        }        else res = 1;        repd (j, min(i + 6, sz(a) - 1), i) {            res = res * 2 + a[j];        }        printf("%02X", res);    }}int main(){    int T;    //freopen("I.out", "w", stdout);    //printf("%02X", 15);    scanf("%d", &T);    getchar();    while (T--) {        gets(s);        int len = strlen(s);        myput(len);        rep (i, len) {            printf("%02X", s[i]);        }               printf("\n");    }    return 0;}

Problem J: JavaBeans

 

Solution

Tag:略

 

/* * Author:  chlxyd * Created Time:  2013/5/29 13:36:41 * File Name: J.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>using namespace std;const double eps(1e-8);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define sz(v) ((int)(v).size())#define rep(i, n) for (int i = 0; i < (n); ++i)#define repf(i, a, b) for (int i = (a); i <= (b); ++i)#define repd(i, a, b) for (int i = (a); i >= (b); --i)#define clrs( x , y ) memset( x , y , sizeof(x) )int T , n , m ;int a[400] , s[400] ;int main(){    scanf("%d" , &T ) ;    repf( t , 1 , T ) {        scanf("%d %d" , &n , &m ) ;        repf( i , 1 , n ) scanf("%d" , &a[i] ) ;        repf( i , n + 1 , n + n ) a[i] = a[i-n] ;        repf( i , 1 , n + n ) s[i] = s[i-1] + a[i] ;        int ans = 0 ;        repf( i , n + 1 , n + n ) ans = max( ans , s[i] - s[i-m] ) ;         printf("%d\n" , ans ) ;    }}

Problem K: KindergartenElection

有n个人,每个人都有一票,现在已知每个人的票会投给谁(不会投给自己),收买一个人需要一定的代价,现在问1需要最少多少钱去收买人,可以让他的票数比其他所有人都多。

 

Solution

Tag:枚举

枚举1胜利时的票数,那么这时胜利的最小费用是可以通过贪心求解的,所有的结果取一个最小值就可以了。

 

/* * Author:  chlxyd * Created Time:  2013/5/29 15:03:54 * File Name: k.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>using namespace std;const double eps(1e-8);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define sz(v) ((int)(v).size())#define rep(i, n) for (int i = 0; i < (n); ++i)#define repf(i, a, b) for (int i = (a); i <= (b); ++i)#define repd(i, a, b) for (int i = (a); i >= (b); --i)#define clrs( x , y ) memset( x , y , sizeof(x) )queue<int> p[110] , tmp[110] , allh ;vector<int> v[110] , all ;int f[110] , c[110] ;int n ;int T ;int solve( int num ) {    int ret = 0 ;    while ( !allh.empty() ) allh.pop() ;    all.clear();    bool flag = true ;    repf( i , 2 , n ) {        while ( p[i].size() >= num ) {            ret += p[i].front() ;            p[1].push(p[i].front()) ;            p[i].pop() ;        }        if ( p[i].size() != num - 1 ) flag = false ;         while ( !p[i].empty() ) {            all.push_back(p[i].front());            p[i].pop() ;        }    }    //cout<<ret<<endl;    //cout<<all.size()<<endl;    sort(all.begin(),all.end());    rep( i , all.size() ) allh.push(all[i]) ;    while ( p[1].size() < num ) {        flag = false ;        ret += allh.front() ;        p[1].push(allh.front()) ;        allh.pop() ;    }    if ( p[1].size() > num ) flag = false ;    if ( flag ) ret += allh.front() ;    return ret ;}int main(){    scanf("%d" , &T ) ;    repf( t , 1 , T ) {         scanf("%d" , &n ) ;        repf( i , 1 , n ) {            v[i].clear() ;            while ( !p[i].empty() ) p[i].pop() ;        }        repf( i , 2 , n )             scanf("%d" , &f[i] ) ;        repf( i , 2 , n )            scanf("%d" , &c[i] ) ;        repf( i , 2 , n )             v[f[i]].push_back(c[i]) ;        repf( i , 1 , n ) sort(v[i].begin(),v[i].end());        repf( i , 1 , n )             rep( j , v[i].size() )                p[i].push(v[i][j]) ;        int ans = 100000000 ;        repd( i , n-1 , 2 ) {            repf( j , 1 , n ) tmp[j] = p[j] ;            //cout<<i<<" "<<solve(i)<<endl;            ans = min( ans , solve( i ) );            repf( j , 1 , n ) p[j] = tmp[j] ;        }         printf("%d\n" , ans ) ;    }}