#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <map>

#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))
#define MP(x,y) make_pair(x,y)
#define EPS 1e-7

#define pii pair<int,int>
#define FFF freopen("test","r",stdin)
#define all(a) a.begin(),a.end()

#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define FORL0(i,a) for(i=a;i>=0;i--)
#define FORL1(i,a) for(i=a;i>=1;i--)
#define FORL(i,a,b)for(i=a;i>=b;i--)

#define rush() int CC;for(scanf("%d",&CC);CC--;)
#define Rush(n)  while(scanf("%d",&n)!=-1)
using namespace std;

void RD(int &x){scanf("%d",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}

void PR(int x) {printf("%d\n",x);}
void PR(int x,int y) {printf("%d %d\n",x,y);}
void PR(u32 x) {printf("%u\n",x);}
void PR(u64 x) {cout<<x<<endl;}
void PR(double x) {printf("%.4lf\n",x);}
void PR(char x) {printf("%c\n",x);}
void PR(char *x) {printf("%s\n",x);}
void PR(string x) {cout<<x<<endl;}

void upMin(int &x,int y) {if(x>y) x=y;}
void upMin(i64 &x,i64 y) {if(x>y) x=y;}
void upMin(double &x,double y) {if(x>y) x=y;}
void upMax(int &x,int y) {if(x<y) x=y;}
void upMax(i64 &x,i64 y) {if(x<y) x=y;}
void upMax(double &x,double y) {if(x<y) x=y;}

int sgn(double x)
{
    if(x>1e-10) return 1;
    if(x<-1e-10) return -1;
    return 0;
}

i64 Gcd(i64 x,i64 y)
{
    if(x<0) x=-x;
    if(y<0) y=-y;
    if(y==0) return x;
    return Gcd(y,x%y);
}

i64 Lcm(i64 x,i64 y)
{
    return x/Gcd(x,y)*y;
}

i64 eular(i64 n)
{
    i64 ans=n,i;
    for(i=2;i*i<=n;i++) if(n%i==0)
    {
        ans-=ans/i;
        while(n%i==0) n/=i;
    }
    if(n>1) ans-=ans/n;
    return ans;
}

i64 exGcd(i64 a,i64 b,i64 &x,i64 &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    i64 temp=exGcd(b,a%b,x,y);
    i64 t=x;
    x=y;
    y=t-a/b*y;
    return temp;
}

i64 gcdReverse(i64 a,i64 b)
{
    i64 x,y;
    exGcd(a,b,x,y);
    x%=b;
    if(x<0) x+=b;
    return x;
}

i64 myPow(i64 a,i64 b)
{
    i64 ans=1;
    while(b)
    {
        if(b&1) ans=ans*a;
        a=a*a;
        b>>=1;
    }
    return ans;
}

i64 myPow(i64 a,i64 b,i64 mod)
{
    a%=mod;
    i64 ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

i64 getInt()
{
    i64 x=0,flag=1;
    char c=getchar();
    while(!isdigit(c)&&c!='-') c=getchar();
    if(c=='-')
    {
        flag=-1,c=getchar();
        while(!isdigit(c)) c=getchar();
    }
    while(isdigit(c))
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*flag;
}

i64 getSqrt(i64 t)
{
    i64 p=sqrt(1.0*t);
    while(p*p>t) p--;
    while((p+1)<=t/(p+1)) p++;
    return p;
}

struct point
{
    double x,y;

    point(){}
    point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }

    void get()
    {
        scanf("%lf%lf",&x,&y);
    }

    point operator+(point a)
    {
        return point(x+a.x,y+a.y);
    }

    point operator-(point a)
    {
        return point(x-a.x,y-a.y);
    }

    point operator*(double t)
    {
        return point(x*t,y*t);
    }

    double operator*(point a)
    {
        return x*a.y-y*a.x;
    }

    double operator^(point a)
    {
        return x*a.x+y*a.y;
    }

    double Len()
    {
        return sqrt(x*x+y*y);
    }

    point adjustTo(double L)
    {
        L/=Len();
        return point(x*L,y*L);
    }

    point operator/(double t)
    {
        return point(x/t,y/t);
    }

    double rotateAngle(point a)
    {
        point p=*this;
        return atan2(p*a,p^a);
    }

    int operator==(point a)
    {
        return sgn(x-a.x)==0&&sgn(y-a.y)==0;
    }

    void print()
    {
        printf("%.4lf %.4lf\n",x,y);
    }
};

double calPloyArea(point a[],int n)
{
    double ans=0;
    int i;
    for(i=0;i<n;i++) ans+=a[i]*a[(i+1)%n];
    return ans;
}

int changeToClockwise(point a[],int n)
{
    double s=calPloyArea(a,n);
    if(sgn(s)>=0) return 0;
    int L=0,R=n-1;
    while(L<R) swap(a[L++],a[R--]);
    return 1;
}

int pointOnSeg(point p,point a,point b)
{
    if(sgn((p-a)*(p-b))) return 0;
    int x=sgn((p.x-a.x)*(p.x-b.x));
    int y=sgn((p.y-a.y)*(p.y-b.y));
    return x<=0&&y<=0;
}

int pointOnRightOfLine(point p,point a,point b)
{
    return sgn((p-a)*(b-a))>0;
}

int pointOnLine(point p,point a,point b)
{
    return sgn((p-a)*(b-a))==0;
}

int pointOnLeftOfLine(point p,point a,point b)
{
    return sgn((b-a)*(p-a))>0;
}

/**
 *out: 1
 * on: 0
 * in: -1
 * */
int getRelationOfPointAndPloy(point a[],int n,point p)
{
    a[n]=a[0];
    int i;
    double sum=0;
    for(i=0;i<n;i++)
    {
        if(pointOnSeg(p,a[i],a[i+1])) return 0;
        point aa=a[i]-p;
        point bb=a[i+1]-p;
        sum+=aa.rotateAngle(bb);
    }

    if(fabs(sum-2*PI)<1e-2) return -1;
    return 1;
}

int isParal(point a,point b,point p,point q)
{
    double aa=(b.x-a.x)*(p.y-q.y);
    double bb=(b.y-a.y)*(p.x-q.x);
    return sgn(aa-bb)==0;
}

/**
 * 1: only one cross
 * 0: no cross
 * 2: many cross
 *
 * */
int lineCrossLine(point a,point b,point p,point q,point &ans)
{
    if(isParal(a,b,p,q))
    {
        if(!pointOnLine(p,a,b)) return 0;
        return 2;
    }

    double s1=(p-a)*(q-a);
    double s2=(q-b)*(p-b);
    ans=(a*s2+b*s1)/(s1+s2);
    return 1;

}

/**
 * 1: only one cross point and store in ans
 * 0: no cross point
 * 2: many cross point
 * */

int segCrossSeg(point a,point b,point p,point q,point &ans)
{
    if(isParal(a,b,p,q))
    {
        if(!pointOnLine(p,a,b)) return 0;
        if(sgn(a.x-b.x)==0)
        {
            if(p.y>q.y) swap(p,q);
            if(a.y>b.y) swap(a,b);
            if(sgn(q.y-a.y)==-1||sgn(b.y-p.y)==-1) return 0;
            if(q==a||p==b)
            {
                if(q==a) ans=q;
                if(p==b) ans=p;
                return 1;
            }
            return 2;
        }
        if(p.x>q.x) swap(p,q);
        if(a.x>b.x) swap(a,b);
        if(sgn(q.x-a.x)==-1||sgn(b.x-p.x)==-1) return 0;
        if(q==a||p==b)
        {
            if(q==a) ans=q;
            if(p==b) ans=p;
            return 1;
        }
        return 2;
    }
    lineCrossLine(a,b,p,q,ans);
    if(pointOnSeg(ans,a,b)&&pointOnSeg(ans,p,q)) return 1;
    return 0;
}

const i64 MM=1000000000000LL;

struct BigInteger
{
    i64 a[105];
    int cnt;

    BigInteger()
    {
        cnt=1;
        a[1]=0;
    }

    BigInteger(i64 x)
    {
        if(x==0)
        {
            cnt=1;
            a[1]=0;
            return;
        }
        cnt=1;
        a[1]=x;
    }

    BigInteger operator*(int x)
    {
        BigInteger p=*this;
        int i;
        FOR1(i,p.cnt) p.a[i]*=x;
        int t=0;
        FOR1(i,p.cnt)
        {
            p.a[i]+=t;
            t=p.a[i]/MM;
            p.a[i]%=MM;
        }
        if(t==0) return p;
        while(t) p.a[++p.cnt]=t%MM,t/=MM;
        return p;
    }

    int zero()
    {
        return cnt==1&&a[1]==0;
    }

    BigInteger operator+(BigInteger a)
    {
        BigInteger p,q;
        if(a.cnt>cnt) p=a,q=*this;
        else p=*this,q=a;

        int i;
        for(i=1;i<=q.cnt;i++) p.a[i]+=q.a[i];
        int re=0;
        for(i=1;i<=p.cnt;i++)
        {
            p.a[i]+=re;
            re=p.a[i]/MM;
            p.a[i]%=MM;
        }
        if(re)
        {
            p.a[++p.cnt]=re;
        }
        return p;
    }

};

struct fraction
{
    i64 a,b;

    fraction()
    {
        a=0;
        b=1;
    }
    fraction(i64 x)
    {
        a=x; b=1;
    }

    fraction(i64 x,i64 y)
    {
        a=x; b=y;
        deal();
    }

    void deal()
    {
        if(b<0) b=-b,a=-a;
        i64 k=Gcd(a,b);
        if(k<0) k=-k;
        a/=k; b/=k;
    }

    fraction operator+(fraction p)
    {
        fraction ans;
        ans.b=Lcm(b,p.b);
        ans.a=ans.b/b*a+ans.b/p.b*p.a;
        ans.deal();
        return ans;
    }

    fraction operator-(fraction p)
    {
        fraction ans;
        ans.b=Lcm(b,p.b);
        ans.a=ans.b/b*a-ans.b/p.b*p.a;
        ans.deal();
        return ans;
    }

    fraction operator*(fraction p)
    {
        fraction ans;
        ans.a=a*p.a;
        ans.b=b*p.b;
        ans.deal();
        return ans;
    }

    fraction operator/(fraction p)
    {
        fraction ans;
        ans.a=a*p.b;
        ans.b=b*p.a;
        ans.deal();
        return ans;
    }

    int operator==(fraction p)
    {
        return a*p.b==b*p.a;
    }

    int operator!=(fraction p)
    {
        if((*this)==p) return 0;
        return 1;
    }

    int isZero()
    {
        return a==0;
    }

};

int matrixSize;
const int matrixMod=45989;

struct Matrix
{
    i64 a[122][122];

    void init(int t=0)
    {
        int i,j;
        FOR0(i,matrixSize) FOR0(j,matrixSize) a[i][j]=0;
        if(t)
        {
            FOR0(i,matrixSize) a[i][i]=1;
        }
    }

    Matrix operator*(Matrix p)
    {
        Matrix ans;
        ans.init();
        int i,j,k;
        int x=matrixSize;
        FOR0(k,x) FOR0(i,x) FOR0(j,x)
        {
            ans.a[i][j]+=a[i][k]*p.a[k][j]%matrixMod;
            ans.a[i][j]%=matrixMod;
        }
        return ans;
    }

    Matrix pow(i64 t)
    {
        Matrix p=*this,ans;
        ans.init(1);
        while(t)
        {
            if(t&1) ans=ans*p;
            p=p*p;
            t>>=1;
        }
        return ans;
    }
};

const int mod=19930726;
const i64 inf=(((i64)1)<<61)+5;
const double dinf=1000000000;
const int INF=1000000005;
const int N=1000005;

struct node
{
    int w,u,v;

    void get()
    {
        RD(u,v,w);
    }

    int operator<(const node &a) const
    {
        return w<a.w;
    }
};

node a[N];
int n;
int S[N],size[N],tot[N],sum;
int flag;

int get(int x)
{
    if(S[x]!=x) S[x]=get(S[x]);
    return S[x];
}

void unite(int x,int y)
{
    x=get(x);
    y=get(y);

    size[x]+=size[y];
    tot[x]+=tot[y];
    S[y]=x;
    if(tot[x]>sum-size[x]) flag=1;
}

int main()
{
    RD(n);
    int i;
    FOR1(i,n-1) a[i].get();
    sort(a+1,a+n);
    FOR1(i,n)
    {
        RD(size[i]);
        tot[i]=1;
        S[i]=i;
        sum+=size[i];
    }
    FOR1(i,n-1) if(tot[i]>sum-size[i]) flag=1;
    int ans=0;
    if(!flag) ans=a[0].w;
    for(i=1;i<=n-1;)
    {
        int j=i;
        while(j<=n-1&&a[i].w==a[j].w)
        {
            unite(a[j].u,a[j].v);
            j++;
        }
        if(!flag&&j<=n-1) ans=a[j].w;
        i=j;
    }
    PR(ans);
}


#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <map>

#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))
#define MP(x,y) make_pair(x,y)
#define EPS 1e-7

#define pii pair<int,int>
#define FFF freopen("test","r",stdin)
#define all(a) a.begin(),a.end()

#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define FORL0(i,a) for(i=a;i>=0;i--)
#define FORL1(i,a) for(i=a;i>=1;i--)
#define FORL(i,a,b)for(i=a;i>=b;i--)

#define rush() int CC;for(scanf("%d",&CC);CC--;)
#define Rush(n)  while(scanf("%d",&n)!=-1)
using namespace std;

void RD(int &x){scanf("%d",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}

void PR(int x) {printf("%d\n",x);}
void PR(int x,int y) {printf("%d %d\n",x,y);}
void PR(u32 x) {printf("%u\n",x);}
void PR(u64 x) {cout<<x<<endl;}
void PR(double x) {printf("%.4lf\n",x);}
void PR(char x) {printf("%c\n",x);}
void PR(char *x) {printf("%s\n",x);}
void PR(string x) {cout<<x<<endl;}

void upMin(int &x,int y) {if(x>y) x=y;}
void upMin(i64 &x,i64 y) {if(x>y) x=y;}
void upMin(double &x,double y) {if(x>y) x=y;}
void upMax(int &x,int y) {if(x<y) x=y;}
void upMax(i64 &x,i64 y) {if(x<y) x=y;}
void upMax(double &x,double y) {if(x<y) x=y;}

int sgn(double x)
{
    if(x>1e-10) return 1;
    if(x<-1e-10) return -1;
    return 0;
}

i64 Gcd(i64 x,i64 y)
{
    if(x<0) x=-x;
    if(y<0) y=-y;
    if(y==0) return x;
    return Gcd(y,x%y);
}

i64 Lcm(i64 x,i64 y)
{
    return x/Gcd(x,y)*y;
}

i64 eular(i64 n)
{
    i64 ans=n,i;
    for(i=2;i*i<=n;i++) if(n%i==0)
    {
        ans-=ans/i;
        while(n%i==0) n/=i;
    }
    if(n>1) ans-=ans/n;
    return ans;
}

i64 exGcd(i64 a,i64 b,i64 &x,i64 &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    i64 temp=exGcd(b,a%b,x,y);
    i64 t=x;
    x=y;
    y=t-a/b*y;
    return temp;
}

i64 gcdReverse(i64 a,i64 b)
{
    i64 x,y;
    exGcd(a,b,x,y);
    x%=b;
    if(x<0) x+=b;
    return x;
}

i64 myPow(i64 a,i64 b)
{
    i64 ans=1;
    while(b)
    {
        if(b&1) ans=ans*a;
        a=a*a;
        b>>=1;
    }
    return ans;
}

i64 myPow(i64 a,i64 b,i64 mod)
{
    a%=mod;
    i64 ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

i64 getInt()
{
    i64 x=0,flag=1;
    char c=getchar();
    while(!isdigit(c)&&c!='-') c=getchar();
    if(c=='-')
    {
        flag=-1,c=getchar();
        while(!isdigit(c)) c=getchar();
    }
    while(isdigit(c))
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*flag;
}

i64 getSqrt(i64 t)
{
    i64 p=sqrt(1.0*t);
    while(p*p>t) p--;
    while((p+1)<=t/(p+1)) p++;
    return p;
}

struct point
{
    double x,y;

    point(){}
    point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }

    void get()
    {
        scanf("%lf%lf",&x,&y);
    }

    point operator+(point a)
    {
        return point(x+a.x,y+a.y);
    }

    point operator-(point a)
    {
        return point(x-a.x,y-a.y);
    }

    point operator*(double t)
    {
        return point(x*t,y*t);
    }

    double operator*(point a)
    {
        return x*a.y-y*a.x;
    }

    double operator^(point a)
    {
        return x*a.x+y*a.y;
    }

    double Len()
    {
        return sqrt(x*x+y*y);
    }

    point adjustTo(double L)
    {
        L/=Len();
        return point(x*L,y*L);
    }

    point operator/(double t)
    {
        return point(x/t,y/t);
    }

    double rotateAngle(point a)
    {
        point p=*this;
        return atan2(p*a,p^a);
    }

    int operator==(point a)
    {
        return sgn(x-a.x)==0&&sgn(y-a.y)==0;
    }

    void print()
    {
        printf("%.4lf %.4lf\n",x,y);
    }
};

double calPloyArea(point a[],int n)
{
    double ans=0;
    int i;
    for(i=0;i<n;i++) ans+=a[i]*a[(i+1)%n];
    return ans;
}

int changeToClockwise(point a[],int n)
{
    double s=calPloyArea(a,n);
    if(sgn(s)>=0) return 0;
    int L=0,R=n-1;
    while(L<R) swap(a[L++],a[R--]);
    return 1;
}

int pointOnSeg(point p,point a,point b)
{
    if(sgn((p-a)*(p-b))) return 0;
    int x=sgn((p.x-a.x)*(p.x-b.x));
    int y=sgn((p.y-a.y)*(p.y-b.y));
    return x<=0&&y<=0;
}

int pointOnRightOfLine(point p,point a,point b)
{
    return sgn((p-a)*(b-a))>0;
}

int pointOnLine(point p,point a,point b)
{
    return sgn((p-a)*(b-a))==0;
}

int pointOnLeftOfLine(point p,point a,point b)
{
    return sgn((b-a)*(p-a))>0;
}

/**
 *out: 1
 * on: 0
 * in: -1
 * */
int getRelationOfPointAndPloy(point a[],int n,point p)
{
    a[n]=a[0];
    int i;
    double sum=0;
    for(i=0;i<n;i++)
    {
        if(pointOnSeg(p,a[i],a[i+1])) return 0;
        point aa=a[i]-p;
        point bb=a[i+1]-p;
        sum+=aa.rotateAngle(bb);
    }

    if(fabs(sum-2*PI)<1e-2) return -1;
    return 1;
}

int isParal(point a,point b,point p,point q)
{
    double aa=(b.x-a.x)*(p.y-q.y);
    double bb=(b.y-a.y)*(p.x-q.x);
    return sgn(aa-bb)==0;
}

/**
 * 1: only one cross
 * 0: no cross
 * 2: many cross
 *
 * */
int lineCrossLine(point a,point b,point p,point q,point &ans)
{
    if(isParal(a,b,p,q))
    {
        if(!pointOnLine(p,a,b)) return 0;
        return 2;
    }

    double s1=(p-a)*(q-a);
    double s2=(q-b)*(p-b);
    ans=(a*s2+b*s1)/(s1+s2);
    return 1;

}

/**
 * 1: only one cross point and store in ans
 * 0: no cross point
 * 2: many cross point
 * */

int segCrossSeg(point a,point b,point p,point q,point &ans)
{
    if(isParal(a,b,p,q))
    {
        if(!pointOnLine(p,a,b)) return 0;
        if(sgn(a.x-b.x)==0)
        {
            if(p.y>q.y) swap(p,q);
            if(a.y>b.y) swap(a,b);
            if(sgn(q.y-a.y)==-1||sgn(b.y-p.y)==-1) return 0;
            if(q==a||p==b)
            {
                if(q==a) ans=q;
                if(p==b) ans=p;
                return 1;
            }
            return 2;
        }
        if(p.x>q.x) swap(p,q);
        if(a.x>b.x) swap(a,b);
        if(sgn(q.x-a.x)==-1||sgn(b.x-p.x)==-1) return 0;
        if(q==a||p==b)
        {
            if(q==a) ans=q;
            if(p==b) ans=p;
            return 1;
        }
        return 2;
    }
    lineCrossLine(a,b,p,q,ans);
    if(pointOnSeg(ans,a,b)&&pointOnSeg(ans,p,q)) return 1;
    return 0;
}

const i64 MM=1000000000000LL;

struct BigInteger
{
    i64 a[105];
    int cnt;

    BigInteger()
    {
        cnt=1;
        a[1]=0;
    }

    BigInteger(i64 x)
    {
        if(x==0)
        {
            cnt=1;
            a[1]=0;
            return;
        }
        cnt=1;
        a[1]=x;
    }

    BigInteger operator*(int x)
    {
        BigInteger p=*this;
        int i;
        FOR1(i,p.cnt) p.a[i]*=x;
        int t=0;
        FOR1(i,p.cnt)
        {
            p.a[i]+=t;
            t=p.a[i]/MM;
            p.a[i]%=MM;
        }
        if(t==0) return p;
        while(t) p.a[++p.cnt]=t%MM,t/=MM;
        return p;
    }

    int zero()
    {
        return cnt==1&&a[1]==0;
    }

    BigInteger operator+(BigInteger a)
    {
        BigInteger p,q;
        if(a.cnt>cnt) p=a,q=*this;
        else p=*this,q=a;

        int i;
        for(i=1;i<=q.cnt;i++) p.a[i]+=q.a[i];
        int re=0;
        for(i=1;i<=p.cnt;i++)
        {
            p.a[i]+=re;
            re=p.a[i]/MM;
            p.a[i]%=MM;
        }
        if(re)
        {
            p.a[++p.cnt]=re;
        }
        return p;
    }

};

struct fraction
{
    i64 a,b;

    fraction()
    {
        a=0;
        b=1;
    }
    fraction(i64 x)
    {
        a=x; b=1;
    }

    fraction(i64 x,i64 y)
    {
        a=x; b=y;
        deal();
    }

    void deal()
    {
        if(b<0) b=-b,a=-a;
        i64 k=Gcd(a,b);
        if(k<0) k=-k;
        a/=k; b/=k;
    }

    fraction operator+(fraction p)
    {
        fraction ans;
        ans.b=Lcm(b,p.b);
        ans.a=ans.b/b*a+ans.b/p.b*p.a;
        ans.deal();
        return ans;
    }

    fraction operator-(fraction p)
    {
        fraction ans;
        ans.b=Lcm(b,p.b);
        ans.a=ans.b/b*a-ans.b/p.b*p.a;
        ans.deal();
        return ans;
    }

    fraction operator*(fraction p)
    {
        fraction ans;
        ans.a=a*p.a;
        ans.b=b*p.b;
        ans.deal();
        return ans;
    }

    fraction operator/(fraction p)
    {
        fraction ans;
        ans.a=a*p.b;
        ans.b=b*p.a;
        ans.deal();
        return ans;
    }

    int operator==(fraction p)
    {
        return a*p.b==b*p.a;
    }

    int operator!=(fraction p)
    {
        if((*this)==p) return 0;
        return 1;
    }

    int isZero()
    {
        return a==0;
    }

};

int matrixSize;
const int matrixMod=45989;

struct Matrix
{
    i64 a[122][122];

    void init(int t=0)
    {
        int i,j;
        FOR0(i,matrixSize) FOR0(j,matrixSize) a[i][j]=0;
        if(t)
        {
            FOR0(i,matrixSize) a[i][i]=1;
        }
    }

    Matrix operator*(Matrix p)
    {
        Matrix ans;
        ans.init();
        int i,j,k;
        int x=matrixSize;
        FOR0(k,x) FOR0(i,x) FOR0(j,x)
        {
            ans.a[i][j]+=a[i][k]*p.a[k][j]%matrixMod;
            ans.a[i][j]%=matrixMod;
        }
        return ans;
    }

    Matrix pow(i64 t)
    {
        Matrix p=*this,ans;
        ans.init(1);
        while(t)
        {
            if(t&1) ans=ans*p;
            p=p*p;
            t>>=1;
        }
        return ans;
    }
};

const int mod=19930726;
const i64 inf=(((i64)1)<<61)+5;
const double dinf=1000000000;
const int INF=1000000005;
const int N=1000005;

struct node
{
    int w,u,v;

    void get()
    {
        RD(u,v,w);
    }

    int operator<(const node &a) const
    {
        return w<a.w;
    }
};

node a[N];
int n;
int S[N],size[N],tot[N],sum;
int flag;

int get(int x)
{
    if(S[x]!=x) S[x]=get(S[x]);
    return S[x];
}

void unite(int x,int y)
{
    x=get(x);
    y=get(y);

    size[x]+=size[y];
    tot[x]+=tot[y];
    S[y]=x;
    if(tot[x]>sum-size[x]) flag=1;
}

int main()
{
    RD(n);
    int i;
    FOR1(i,n-1) a[i].get();
    sort(a+1,a+n);
    FOR1(i,n)
    {
        RD(size[i]);
        tot[i]=1;
        S[i]=i;
        sum+=size[i];
    }
    FOR1(i,n-1) if(tot[i]>sum-size[i]) flag=1;
    int ans=0;
    if(!flag) ans=a[1].w;
    for(i=1;i<=n-1;)
    {
        int j=i;
        while(j<=n-1&&a[i].w==a[j].w)
        {
            unite(a[j].u,a[j].v);
            j++;
        }
        if(!flag&&j<n) ans=a[j].w;
        i=j;
    }
    PR(ans);
}


#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int N=3050;
struct node{
  int x,y,c;
}E[N];
bool cmp(node x,node y){
  return x.c<y.c;
}
int fa[N],s[N],x[N];
int getf(int v){
  if(v==fa[v])return v;
  return fa[v]=getf(fa[v]);
}

int main(){
  int n;scanf("%d",&n);
  for(int i=1;i<n;i++)scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].c);
  sort(E+1,E+n,cmp);
  int sum=0;
  for(int i=1;i<=n;i++){
    scanf("%d",&x[i]);
    sum+=x[i];
    fa[i]=i;
    s[i]=1;
  }
  for(int i=1;i<n;i++){
    int u=getf(E[i].x),v=getf(E[i].y);
    fa[u]=v;s[v]+=s[u];x[v]+=x[u];
    if(s[v]>sum-x[v]){
      printf("%d\n",E[i].c);
      return 0;
    }
  }
}


#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int N=3050;
struct node{
  int x,y,c;
}E[N];
bool cmp(node x,node y){
  return x.c<y.c;
}
int fa[N],s[N],x[N];
int getf(int v){
  if(v==fa[v])return v;
  return fa[v]=getf(fa[v]);
}

int main(){
  int n;scanf("%d",&n);
  for(int i=1;i<n;i++)scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].c);
  sort(E+1,E+n,cmp);
  int sum=0;
  for(int i=1;i<=n;i++){
    scanf("%d",&x[i]);
    sum+=x[i];
    fa[i]=i;
    s[i]=1;
  }
  for(int i=1;i<n;i++){
    int u=getf(E[i].x),v=getf(E[i].y);
    fa[u]=v;s[v]+=s[u];x[v]+=x[u];
    if(s[v]>sum-x[v]){
      printf("%d\n",E[i].c);
      return 0;
    }
  }
  printf("0");
}


#include <iostream>
#include <algorithm>

using namespace std;

typedef pair<int, int> pii;

const int MAXN = 3001;
int ex[MAXN], ey[MAXN], w[MAXN], f[MAXN], sum, par[MAXN], sz[MAXN], sumF[MAXN];
pii all[MAXN];
bool bad;

int find(int x) {
	if (par[x] != x)
		par[x] = find(par[x]);
	return par[x];
}

void merge(int x, int y) {
	x = find(x); y = find(y);
	if (x == y)
		return;
	sz[x] += sz[y];
	sumF[x] += sumF[y];
	par[y] = x;
	if (sum - sumF[x] < sz[x])
		bad = true;
}

int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n - 1; i++) {
		cin >> ex[i] >> ey[i] >> w[i];
		ex[i]--; ey[i]--;
		all[i] = pii(w[i], i);
	}
	for (int i = 0; i < n; i++)
		cin >> f[i], sum += f[i], sumF[i] = f[i], par[i] = i, sz[i] = 1;
	sort(all, all + n - 1);
	int ans = 0, cur = 0;
	while (cur < n - 1) {
		int edgeId = all[cur].second;
		if (!bad)
			ans = w[edgeId];
		merge(ex[edgeId], ey[edgeId]);
		while (cur < n - 1 && w[edgeId] == w[all[cur].second])
			cur++;
	}
	if (!bad && n > 1)
		ans = w[n - 2];
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <algorithm>

using namespace std;

typedef pair<int, int> pii;

const int MAXN = 3001;
int ex[MAXN], ey[MAXN], w[MAXN], f[MAXN], sum, par[MAXN], sz[MAXN], sumF[MAXN];
pii all[MAXN];
bool bad;

int find(int x) {
	if (par[x] != x)
		par[x] = find(par[x]);
	return par[x];
}

void merge(int x, int y) {
	x = find(x); y = find(y);
	if (x == y)
		return;
	sz[x] += sz[y];
	sumF[x] += sumF[y];
	par[y] = x;
	if (sum - sumF[x] < sz[x])
		bad = true;
}

int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n - 1; i++) {
		int x, y, c;
		cin >> x >> y >> c;
		x--; y--;
		ex[i] = x;
		ey[i] = y;
		w[i] = c;
		all[i] = pii(c, i);
	}
	for (int i = 0; i < n; i++)
		cin >> f[i], sum += f[i], sumF[i] = f[i], par[i] = i, sz[i] = 1;
	sort(all, all + n - 1);
	int ans = 0, cur = 0;
	while (cur < n - 1) {
		int edgeId = all[cur].second;
		if (!bad)
			ans = w[edgeId];
		merge(ex[edgeId], ey[edgeId]);
		while (cur < n - 1 && w[edgeId] == w[all[cur].second])
			cur++;
	}
	if (!bad && n > 1)
		ans = w[n - 1];
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <algorithm>

using namespace std;

typedef pair<int, int> pii;

const int MAXN = 3001;
int ex[MAXN], ey[MAXN], w[MAXN], f[MAXN], sum, par[MAXN], sz[MAXN], sumF[MAXN];
pii all[MAXN];
bool bad;

int find(int x) {
	if (par[x] != x)
		par[x] = find(par[x]);
	return par[x];
}

void merge(int x, int y) {
	x = find(x); y = find(y);
	if (x == y)
		return;
	sz[x] += sz[y];
	sumF[x] += sumF[y];
	par[y] = x;
	if (sum - sumF[x] < sz[x])
		bad = true;
}

int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n - 1; i++) {
		cin >> ex[i] >> ey[i] >> w[i];
		ex[i]--; ey[i]--;
		all[i] = pii(w[i], i);
	}
	for (int i = 0; i < n; i++)
		cin >> f[i], sum += f[i], sumF[i] = f[i], par[i] = i, sz[i] = 1;
	sort(all, all + n - 1);
	int ans = 0, cur = 0;
	while (cur < n - 1) {
		int edgeId = all[cur].second;
		if (!bad)
			ans = w[edgeId];
		merge(ex[edgeId], ey[edgeId]);
		while (cur < n - 1 && w[edgeId] == w[all[cur].second])
			cur++;
	}
	if (!bad && n > 1)
		ans = w[all[n - 2].second];
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <algorithm>

using namespace std;

typedef pair<int, int> pii;

const int MAXN = 3001;
int ex[MAXN], ey[MAXN], w[MAXN], f[MAXN], sum, par[MAXN], sz[MAXN], sumF[MAXN];
pii all[MAXN];
bool bad;

int find(int x) {
	if (par[x] != x)
		par[x] = find(par[x]);
	return par[x];
}

void merge(int x, int y) {
	x = find(x); y = find(y);
	if (x == y)
		return;
	sz[x] += sz[y];
	sumF[x] += sumF[y];
	par[y] = x;
	if (sum - sumF[x] < sz[x])
		bad = true;
}

int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n - 1; i++) {
		cin >> ex[i] >> ey[i] >> w[i];
		ex[i]--; ey[i]--;
		all[i] = pii(w[i], i);
	}
	for (int i = 0; i < n; i++)
		cin >> f[i], sum += f[i], sumF[i] = f[i], par[i] = i, sz[i] = 1;
	sort(all, all + n - 1);
	int ans = 0, cur = 0;
	while (cur < n - 1) {
		int edgeId = all[cur].second;
		if (!bad)
			ans = w[edgeId];
		merge(ex[edgeId], ey[edgeId]);
		while (cur < n - 1 && w[edgeId] == all[cur].first)
			merge(ex[all[cur].second], ey[all[cur].second]), cur++;
	}
	if (!bad && n > 1)
		ans = w[all[n - 2].second];
	cout << ans << endl;
	return 0;
}


#include <cstdio>
#include <numeric>
#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <bitset>
#include <queue>
#include <sstream>
#include <deque>
#include <cassert>

using namespace std;

#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i = 0; i < (n); i++)
#define re return
#define fi first
#define se second
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqr(x) ((x) * (x))
#define sqrt(x) sqrt(abs(x))
#define y0 y3487465
#define y1 y8687969
#define fill(x,y) memset(x,y,sizeof(x))
#define prev PREV
#define j0 j1347829
#define j1 j234892

typedef vector<int> vi;
typedef long long ll;
typedef long double ld;
typedef double D;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef vector<vi> vvi;

template<class T> T abs(T x) { re x > 0 ? x : -x; }

int n;
int m;
int p[10000];
int x[10000];
int y[10000];
int w[10000];
vector<pair<int, ii> > v;

int gp (int x) {
    if (p[x] == x) re x;
    re p[x] = gp (p[x]);
}

int can (int h) {
    for (int i = 0; i < n; i++) {
        p[i] = i;
        x[i] = 1;
        y[i] = w[i];
    }
    for (int i = 0; i < h; i++) {
        int a = gp (v[i].se.fi);
        int b = gp (v[i].se.se);
        if (a != b) {
            p[a] = b;
            x[b] += x[a];
            y[b] += y[a];
        }
    }
    int sx = 0, sy = 0;
    vii u;
    for (int i = 0; i < n; i++)
        if (p[i] == i) {
            u.pb (mp (x[i], y[i]));
            sx += x[i];
            sy += y[i];
        }
    for (int i = 0; i < sz (u); i++)
        if (u[i].fi > sy - u[i].se)
            re 0;
    re 1;
}

int main () {
    scanf ("%d", &n);
    for (int i = 0; i + 1 < n; i++) {
        int a, b, c;
        scanf ("%d%d%d", &a, &b, &c); a--; b--;
        v.pb (mp (c, mp (a, b)));
    }
    for (int i = 0; i < n; i++) scanf ("%d", &w[i]);
    sort (all (v));
    int l = 0, r = n;
    while (r - l > 1) {
        int s = (l + r) / 2;
        if (can (s)) l = s; else r = s;
    }
    printf ("%d\n", v[l].fi);
    return 0;
}


#include <cstdio>
#include <numeric>
#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <bitset>
#include <queue>
#include <sstream>
#include <deque>
#include <cassert>

using namespace std;

#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i = 0; i < (n); i++)
#define re return
#define fi first
#define se second
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqr(x) ((x) * (x))
#define sqrt(x) sqrt(abs(x))
#define y0 y3487465
#define y1 y8687969
#define fill(x,y) memset(x,y,sizeof(x))
#define prev PREV
#define j0 j1347829
#define j1 j234892

typedef vector<int> vi;
typedef long long ll;
typedef long double ld;
typedef double D;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef vector<vi> vvi;

template<class T> T abs(T x) { re x > 0 ? x : -x; }

int n;
int m;
int p[10000];
int x[10000];
int y[10000];
int w[10000];
vector<pair<int, ii> > v;

int gp (int x) {
    if (p[x] == x) re x;
    re p[x] = gp (p[x]);
}

int can (int h) {
    for (int i = 0; i < n; i++) {
        p[i] = i;
        x[i] = 1;
        y[i] = w[i];
    }
    for (int i = 0; i < h; i++) {
        int a = gp (v[i].se.fi);
        int b = gp (v[i].se.se);
        if (a != b) {
            p[a] = b;
            x[b] += x[a];
            y[b] += y[a];
        }
    }
    int sx = 0, sy = 0;
    vii u;
    for (int i = 0; i < n; i++)
        if (p[i] == i) {
            u.pb (mp (x[i], y[i]));
            sx += x[i];
            sy += y[i];
        }
    for (int i = 0; i < sz (u); i++)
        if (u[i].fi > sy - u[i].se)
            re 0;
    re 1;
}

int main () {
    scanf ("%d", &n);
    for (int i = 0; i + 1 < n; i++) {
        int a, b, c;
        scanf ("%d%d%d", &a, &b, &c); a--; b--;
        v.pb (mp (c, mp (a, b)));
    }
    for (int i = 0; i < n; i++) scanf ("%d", &w[i]);
    sort (all (v));
    int l = 0, r = n;
    while (r - l > 1) {
        int s = (l + r) / 2;
        if (can (s)) l = s; else r = s;
    }
    if (l == n - 1) printf ("0\n"); else printf ("%d\n", v[l].fi);
    return 0;
}


#include <cstdio>
#include <numeric>
#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <bitset>
#include <queue>
#include <sstream>
#include <deque>
#include <cassert>

using namespace std;

#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i = 0; i < (n); i++)
#define re return
#define fi first
#define se second
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqr(x) ((x) * (x))
#define sqrt(x) sqrt(abs(x))
#define y0 y3487465
#define y1 y8687969
#define fill(x,y) memset(x,y,sizeof(x))
#define prev PREV
#define j0 j1347829
#define j1 j234892

typedef vector<int> vi;
typedef long long ll;
typedef long double ld;
typedef double D;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef vector<vi> vvi;

template<class T> T abs(T x) { re x > 0 ? x : -x; }

int n;
int m;
int p[10000];
int x[10000];
int y[10000];
int w[10000];
pair<int, ii> v[10000];

int gp (int x) {
    if (p[x] == x) re x;
    re p[x] = gp (p[x]);
}

int can (int h) {
    for (int i = 0; i < n; i++) {
        p[i] = i;
        x[i] = 1;
        y[i] = w[i];
    }
    for (int i = 0; i < h; i++) {
        int a = gp (v[i].se.fi);
        int b = gp (v[i].se.se);
        if (a != b) {
            p[a] = b;
            x[b] += x[a];
            y[b] += y[a];
        }
    }
    int sx = 0, sy = 0;
    vii u;
    for (int i = 0; i < n; i++)
        if (p[i] == i) {
            u.pb (mp (x[i], y[i]));
            sx += x[i];
            sy += y[i];
        }
    for (int i = 0; i < sz (u); i++)
        if (u[i].fi > sy - u[i].se)
            re 0;
    re 1;
}

int main () {
    scanf ("%d", &n);
    for (int i = 0; i + 1 < n; i++) {
        int a, b, c;
        scanf ("%d%d%d", &a, &b, &c); a--; b--;
        v[i] = mp (c, mp (a, b));
    }
    for (int i = 0; i < n; i++) scanf ("%d", &w[i]);
    sort (v, v + n - 1);
    int l = 0, r = n;
    while (r - l > 1) {
        int s = (l + r) / 2;
        if (can (s)) l = s; else r = s;
    }
    printf ("%d\n", v[l].fi);
    return 0;
}


#include <cstdio>
#include <numeric>
#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <bitset>
#include <queue>
#include <sstream>
#include <deque>
#include <cassert>

using namespace std;

#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i = 0; i < (n); i++)
#define re return
#define fi first
#define se second
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqr(x) ((x) * (x))
#define sqrt(x) sqrt(abs(x))
#define y0 y3487465
#define y1 y8687969
#define fill(x,y) memset(x,y,sizeof(x))
#define prev PREV
#define j0 j1347829
#define j1 j234892

typedef vector<int> vi;
typedef long long ll;
typedef long double ld;
typedef double D;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef vector<vi> vvi;

template<class T> T abs(T x) { re x > 0 ? x : -x; }

int n;
int m;
int p[10000];
int x[10000];
int y[10000];
int w[10000];
vector<pair<int, ii> > v;

int gp (int x) {
    if (p[x] == x) re x;
    re p[x] = gp (p[x]);
}

int can (int h) {
    for (int i = 0; i < n; i++) {
        p[i] = i;
        x[i] = 1;
        y[i] = w[i];
    }
    for (int i = 0; i < h; i++) {
        int a = gp (v[i].se.fi);
        int b = gp (v[i].se.se);
        if (a != b) {
            p[a] = b;
            x[b] += x[a];
            y[b] += y[a];
        }
    }
    int sx = 0, sy = 0;
    vii u;
    for (int i = 0; i < n; i++)
        if (p[i] == i) {
            u.pb (mp (x[i], y[i]));
            sx += x[i];
            sy += y[i];
        }
    for (int i = 0; i < sz (u); i++)
        if (u[i].fi > sy - u[i].se)
            re 0;
    re 1;
}

int main () {
    scanf ("%d", &n);
    for (int i = 0; i + 1 < n; i++) {
        int a, b, c;
        scanf ("%d%d%d", &a, &b, &c); a--; b--;
        v.pb (mp (c, mp (a, b)));
    }
    for (int i = 0; i < n; i++) scanf ("%d", &w[i]);
    sort (all (v));
    int l = 0, r = n - 1;
    while (r - l > 1) {
        int s = (l + r) / 2;
        if (can (s)) l = s; else r = s;
    }
    printf ("%d\n", v[l].fi);
    return 0;
}


#include <cstdio>
#include <cmath>

int n;

int x[4000];

int adj[4000];
int aim[8000], next[8000], weight[8000];

int visit[4000];
int sumx[4000];
int count[4000];

int ans;

void dfs(int r, int w, int s)
{
	visit[r] = 1;
	sumx[s] += x[r];
	count[s] += 1;

	int i = adj[r];

	while (i)
	{
		if (weight[i] < w && !visit[aim[i]])
			dfs(aim[i], w, s);
		i = next[i];
	}
}

int check(int w)
{
	int flex = 0;

	for (int i = 0; i < n; ++i)
	{
		visit[i] = 0; count[i] = 0; sumx[i] = 0;
	}

	for (int i = 0; i < n; ++i)
		if (!visit[i]) dfs(i, w, i);

	for (int i = 0; i < n; ++i)
		flex += sumx[i] - count[i];

	for (int i = 0; i < n; ++i)
		if (count[i] > n / 2)
		{
			if (count[i] - flex + sumx[i] - count[i] > n / 2) return 0;
			break;
		}

	return 1;
}

int main()
{
	scanf("%d", &n);

	int a, b, c;

	for (int i = 0; i < n - 1; ++i)
	{
		scanf("%d %d %d", &a, &b, &c);
		//if (c > r) r = c;
		--a; --b;
		aim[i * 2 + 1] = b; next[i * 2 + 1] = adj[a]; adj[a] = i * 2 + 1;
		aim[i * 2 + 2] = a; next[i * 2 + 2] = adj[b]; adj[b] = i * 2 + 2;
		weight[i * 2 + 1] = weight[i * 2 + 2] = c;
	}

	for (int i = 0; i < n; ++i)
		scanf("%d", &x[i]);

	int l = 0, r = 10000;
	int mid;

	while (r - l > 1)
	{
		mid = (l + r) / 2;
		if (check(mid)) l = mid; else r = mid;
	}

	if (check(r)) ans = r; else ans = l;

	printf("%d\n", ans);

	return 0;
}


#include <cstdio>
#include <cmath>

int n;

int x[4000];

int adj[4000];
int aim[8000], next[8000], weight[8000];

int visit[4000];
int sumx[4000];
int count[4000];

int ans;

void dfs(int r, int w, int s)
{
	visit[r] = 1;
	sumx[s] += x[r];
	count[s] += 1;

	int i = adj[r];

	while (i)
	{
		if (weight[i] < w && !visit[aim[i]])
			dfs(aim[i], w, s);
		i = next[i];
	}
}

int check(int w)
{
	int flex = 0;

	for (int i = 0; i < n; ++i)
	{
		visit[i] = 0; count[i] = 0; sumx[i] = 0;
	}

	for (int i = 0; i < n; ++i)
		if (!visit[i]) dfs(i, w, i);

	for (int i = 0; i < n; ++i)
		flex += sumx[i] - count[i];

	for (int i = 0; i < n; ++i)
		if (count[i] > n / 2)
		{
		if (count[i] - flex + sumx[i] - count[i] > (n - flex + sumx[i] - count[i])/ 2) return 0;
		break;
		}

	return 1;
}

int main()
{
	scanf("%d", &n);

	int a, b, c;

	for (int i = 0; i < n - 1; ++i)
	{
		scanf("%d %d %d", &a, &b, &c);
		//if (c > r) r = c;
		--a; --b;
		aim[i * 2 + 1] = b; next[i * 2 + 1] = adj[a]; adj[a] = i * 2 + 1;
		aim[i * 2 + 2] = a; next[i * 2 + 2] = adj[b]; adj[b] = i * 2 + 2;
		weight[i * 2 + 1] = weight[i * 2 + 2] = c;
	}

	for (int i = 0; i < n; ++i)
		scanf("%d", &x[i]);

	int l = 0, r = 10000;
	int mid;

	while (r - l > 1)
	{
		mid = (l + r) / 2;
		if (check(mid)) l = mid; else r = mid;
	}

	if (check(r)) ans = r; else ans = l;

	printf("%d\n", ans);

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

#define pii pair<int, int>
#define MAXN 100010

vector<pii> edges[MAXN], edgeList;
int a[MAXN], b[MAXN], x[MAXN];
pii dfs(int v, int fat, int den)
{
    pii ans(1, x[v]);
    for (int i = 0; i < edges[v].size(); i++)
        if (edges[v][i].second != den && edges[v][i].first != fat)
        {
            pii x = dfs(edges[v][i].first, v, den);
            ans.first += x.first;
            ans.second += x.second;
        }
    return ans;
}
int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n - 1; i++)
    {
        int  c;
        cin >> a[i] >> b[i] >> c;
        edges[a[i]].push_back(pii(b[i], i));
        edges[b[i]].push_back(pii(a[i], i));
        edgeList.push_back(pii(c, i));
    }
    for (int i = 1; i <= n; i++)
        cin >> x[i];
    sort(edgeList.begin(), edgeList.end(), greater<pii>());
    for (int i = 0; i < edgeList.size(); i++)
    {
        int en = edgeList[i].second;
        pii x = dfs(a[en], -1, en);
        pii y = dfs(b[en], -1, en);
        //cout << a[en] << " " << x.first << " " << b[en] << " " << y. << endl;
        if (x.second >= y.first && y.second >= x.first)
        {
            cout << edgeList[i].first << endl;
            return 0;
        }
    }
    cout << 0 << endl;
}


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

#define pii pair<int, long long>
#define MAXN 100010

vector<pii> edges[MAXN], edgeList;
int a[MAXN], b[MAXN], x[MAXN];
pii dfs(int v, int fat, int den)
{
    pii ans(1, x[v]);
    for (int i = 0; i < edges[v].size(); i++)
        if (edges[v][i].second != den && edges[v][i].first != fat)
        {
            pii x = dfs(edges[v][i].first, v, den);
            ans.first += x.first;
            ans.second += x.second;
        }
    return ans;
}
int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n - 1; i++)
    {
        int  c;
        cin >> a[i] >> b[i] >> c;
        edges[a[i]].push_back(pii(b[i], i));
        edges[b[i]].push_back(pii(a[i], i));
        edgeList.push_back(pii(c, i));
    }
    for (int i = 1; i <= n; i++)
        cin >> x[i];
    sort(edgeList.begin(), edgeList.end(), greater<pii>());
    for (int i = 0; i < edgeList.size(); i++)
    {
        int en = edgeList[i].second;
        pii x = dfs(a[en], -1, en);
        pii y = dfs(b[en], -1, en);
        //cout << a[en] << " " << x.first << " " << b[en] << " " << y. << endl;
        if (x.second >= y.first && y.second >= x.first)
        {
            cout << edgeList[i].first << endl;
            return 0;
        }
    }
    cout << 0 << endl;
}


#include <iostream>
#include <memory.h>
#include <vector>
#include <algorithm>

using namespace std;

#define pii pair<int, int>
#define MAXN 100010

vector<pii> edges[MAXN];
vector<int> edgeList;
int x[MAXN];
bool marked[MAXN];
pii dfs(int v, int c)
{
    pii ans(1, x[v]);
    marked[v] = true;
    for (int i = 0; i < edges[v].size(); i++)
        if (edges[v][i].second < c && !marked[edges[v][i].first])
        {
            pii x = dfs(edges[v][i].first, c);
            ans.first += x.first;
            ans.second += x.second;
        }
    return ans;
}
int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n - 1; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        edges[a].push_back(pii(b, c));
        edges[b].push_back(pii(a, c));
        edgeList.push_back(c);
    }
    for (int i = 1; i <= n; i++)
        cin >> x[i];
    sort(edgeList.begin(), edgeList.end());
    edgeList.resize(unique(edgeList.begin(), edgeList.end()) - edgeList.begin());
    for (int i = edgeList.size() - 1; i >= 0; i--)
    {
        int ans = 0;
        pii ans2(0, 0);
        memset(marked, false, sizeof marked);
        for (int j = 1; j <= n; j++)
            if (!marked[j])
            {
                pii x = dfs(j, edgeList[i]);
                //cout << edgeList[i] << " " << j << " " << x.first << " " << x.second << "-----\n";
                ans += x.second;
                ans2 = max(ans2, x);
            }
        //cout << ans << " " << ans2 << " " << ans3 << endl;
        if (ans2.first <= ans - ans2.second)
        {
            cout << edgeList[i] << endl;
            return 0;
        }
    }
    cout << 0 << endl;
}


#include <iostream>
#include <memory.h>
#include <vector>
#include <algorithm>

using namespace std;

#define pii pair<int, int>
#define MAXN 100010

vector<pii> edges[MAXN];
vector<int> edgeList;
int x[MAXN];
bool marked[MAXN];
pii dfs(int v, int c)
{
    pii ans(1, x[v]);
    marked[v] = true;
    for (int i = 0; i < edges[v].size(); i++)
        if (edges[v][i].second != c && !marked[edges[v][i].first])
        {
            pii x = dfs(edges[v][i].first, c);
            ans.first += x.first;
            ans.second += x.second;
        }
    return ans;
}
int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n - 1; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        edges[a].push_back(pii(b, c));
        edges[b].push_back(pii(a, c));
        edgeList.push_back(c);
    }
    for (int i = 1; i <= n; i++)
        cin >> x[i];
    sort(edgeList.begin(), edgeList.end());
    edgeList.resize(unique(edgeList.begin(), edgeList.end()) - edgeList.begin());
    for (int i = edgeList.size() - 1; i >= 0; i--)
    {
        int ans = 0;
        pii ans2(0, 0);
        memset(marked, false, sizeof marked);
        for (int j = 1; j <= n; j++)
            if (!marked[j])
            {
                pii x = dfs(j, edgeList[i]);
                //cout << edgeList[i] << " " << j << " " << x.first << " " << x.second << "-----\n";
                ans += x.second;
                ans2 = max(ans2, x);
            }
        //cout << ans << " " << ans2 << " " << ans3 << endl;
        if (ans2.first <= ans - ans2.second)
        {
            cout << edgeList[i] << endl;
            return 0;
        }
    }
    cout << 0 << endl;
}


#include <iostream>
#include <memory.h>
#include <vector>
#include <algorithm>

using namespace std;

#define pii pair<int, int>
#define MAXN 100010

vector<pii> edges[MAXN];
vector<int> edgeList;
int x[MAXN];
bool marked[MAXN];
pii dfs(int v, int c)
{
    pii ans(1, x[v]);
    marked[v] = true;
    for (int i = 0; i < edges[v].size(); i++)
        if (edges[v][i].second != c && !marked[edges[v][i].first])
        {
            pii x = dfs(edges[v][i].first, c);
            ans.first += x.first;
            ans.second += x.second;
        }
    return ans;
}
int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n - 1; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        edges[a].push_back(pii(b, c));
        edges[b].push_back(pii(a, c));
        edgeList.push_back(c);
    }
    for (int i = 1; i <= n; i++)
        cin >> x[i];
    sort(edgeList.begin(), edgeList.end());
    edgeList.resize(unique(edgeList.begin(), edgeList.end()) - edgeList.begin());
    for (int i = edgeList.size() - 1; i >= 0; i--)
    {
        int ans = 0;
        int ans2 = 0;
        int ans3 = 0;
        memset(marked, false, sizeof marked);
        for (int j = 1; j <= n; j++)
            if (!marked[j])
            {
                pii x = dfs(j, edgeList[i]);
                //cout << edgeList[i] << " " << j << " " << x.first << " " << x.second << "-----\n";
                ans += x.second;
                if (x.first > ans2)
                    ans2 = x.first, ans3 = x.second;
                else if (x.first == ans2 && x.second < ans3)
                    ans3 = x.second;
            }
        //cout << ans << " " << ans2 << " " << ans3 << endl;
        if (ans2 <= ans - ans3)
        {
            cout << edgeList[i] << endl;
            return 0;
        }
    }
    cout << 0 << endl;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn = 3000 + 5;
struct edge{
	int u,v,a;
	bool operator < (const edge& c) const{return a < c.a;}
}Set[maxn];
int f[maxn],sz[maxn],out[maxn],sum,N;
int F(int o){return o == f[o]? o: f[o] = F(f[o]);}
int main(){
	//freopen("input.txt","r",stdin);
	scanf("%d",&N);if(N == 1){puts("0");return 0;}
	for(int i = 1;i < N; ++i)
		scanf("%d%d%d",&Set[i].u,&Set[i].v,&Set[i].a);
	for(int i = 1;i <= N; ++i){
		scanf("%d",&sz[i]);
		sum += sz[i];out[i] = 1;f[i] = i;
	}
	sort(Set+1,Set+N);
	for(int i = 1;i < N; i++){
		int u = F(Set[i].u),v = F(Set[i].v);
		if(u != v){
			f[v] = u;
			sz[u] += sz[v];
			out[u] += out[v];
			if(sz[u] + out[u] > sum){
				printf("%d\n",Set[i].a);
				return 0;
			}
		}
	}
}


#include<bits/stdc++.h>
using namespace std;
const int maxn = 3000 + 5;
struct edge{
	int u,v,a;
	bool operator < (const edge& c) const{return a < c.a;}
}Set[maxn];
int f[maxn],sz[maxn],out[maxn],sum,N;
int F(int o){return o == f[o]? o: f[o] = F(f[o]);}
int main(){

	scanf("%d",&N);
	for(int i = 1;i < N; ++i)
		scanf("%d%d%d",&Set[i].u,&Set[i].v,&Set[i].a);
	for(int i = 1;i <= N; ++i){
		scanf("%d",sz[i]);
		sum += sz[i];out[i] = 1;f[i] = i;
	}
	sort(Set+1,Set+N);
	for(int i = 1;i < N; i++){
		int u = F(Set[i].u),v = F(Set[i].v);
		if(u != v){
			f[u] = v;
			sz[u] += sz[v];
			out[u] += out[v];
			if(sz[u] + out[u] >= sum){
				printf("%d",Set[i].a);
				return 0;
			}
		}
	}
}


#include<bits/stdc++.h>
using namespace std;
const int maxn = 3000 + 5;
struct edge{
	int u,v,a;
	bool operator < (const edge& c) const{return a < c.a;}
}Set[maxn];
int f[maxn],sz[maxn],out[maxn],sum,N;
int F(int o){return o == f[o]? o: f[o] = F(f[o]);}
int main(){
	//freopen("input.txt","r",stdin);
	scanf("%d",&N);
	for(int i = 1;i < N; ++i)
		scanf("%d%d%d",&Set[i].u,&Set[i].v,&Set[i].a);
	for(int i = 1;i <= N; ++i){
		scanf("%d",&sz[i]);
		sum += sz[i];out[i] = 1;f[i] = i;
	}
	sort(Set+1,Set+N);
	for(int i = 1;i < N; i++){
		int u = F(Set[i].u),v = F(Set[i].v);
		if(u != v){
			f[v] = u;
			sz[u] += sz[v];
			out[u] += out[v];
			if(sz[u] + out[u] > sum){
				printf("%d",Set[i].a);
				return 0;
			}
		}
	}
}


#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

struct edge {
	int u,v,w;
} e[3005];
inline bool operator <(edge a,edge b) {
	return a.w<b.w;
}
int n,pre[3005],size[3005],num[3005],all,ans;
bool ok;
int find(int x) {
	return pre[x]==x?x:pre[x]=find(pre[x]);
}
inline void merge(int u,int v) {
	u=find(u); v=find(v);
	size[u]+=size[v]; num[u]+=num[v];
	if (size[u]>all-num[u]) ok=false;
	pre[v]=u;
}
int main() {
	scanf("%d",&n);
	for (int i=1;i<n;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
	sort(e+1,e+n);
	for (int i=1;i<=n;i++) {
		pre[i]=i; size[i]=1;
		scanf("%d",&num[i]);
		all+=num[i];
	}
	for (int i=1;i<=n;i++) if (all-num[i]==0) {
		puts("0");
		return 0;
	}
	ok=true;
	ans=e[1].w;
	for (int i=1,j;i<n;i=j) {
		j=i;
		while (j<n&&e[j].w==e[i].w) {
			merge(e[j].u,e[j].v);
			j++;
		}
		if (ok) ans=e[j].w; else break;
	}
	printf("%d\n",ans);
	return 0;
}


#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 3010;

struct edge{
	int u, v, w;
}e[N];

int n, a[N], f[N], sz[N], t[N], sum;

int getf(int x){
	if(f[x] == x) return x;
	else return f[x] = getf(f[x]);
}

bool check(int x){
	for(int i = 1; i <= n; i++){
		f[i] = i; sz[i] = 1; t[i] = a[i];
	}
	for(int i = 1; i < n; i++){
		if(e[i].w < x){
			int u = e[i].u, v = e[i].v;
			u = getf(u); v = getf(v);
			t[u] += t[v]; sz[u] += sz[v];
			f[v] = u;
		}
	}
	for(int i = 1; i <= n; i++){
		if(f[i] == i && sum - t[i] < sz[i]) return false;
	}
	return true;
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i < n; i++)
		scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
	for(int i = 1; i <= n; i++)
		scanf("%d", &a[i]), sum += a[i];

	int lb = 0, rb = 10010;
	while(lb + 1 < rb){
		int mid  = lb + rb >> 1;
		if(check(mid)) lb = mid; else rb = mid;
	}
	printf("%d\n", lb);
}


#include<stdio.h>
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<memory.h>
#include<map>
#include<set>
#include<queue>
#include<list>
#include<sstream>
#include<cstring>
#define mp make_pair
#define pb push_back
#define F first
#define S second
#define SS stringstream
#define sqr(x) ((x)*(x))
#define m0(x) memset(x,0,sizeof(x))
#define m1(x) memset(x,63,sizeof(x))
#define CC(x) cout << (x) << endl
#define pw(x) (1ll<<(x))
#define M 1000000007
#define N 211111
using namespace std;
typedef pair<int,int> pt;

int n;
pair<int, pt> q[3333];
int p[3333], sz[3333], kol[3333];
int maxsz, sum = 0, bad = 0;

int get(int x) {
	if (p[x] == x) return x;
	return p[x] = get(p[x]);
}

void unite(int x, int y) {
	x = get(x);
	y = get(y);
	maxsz = max(maxsz, sz[x] + sz[y]);
	sz[x] += sz[y];
	kol[x] += kol[y];
	if (kol[x] > sum - sz[x]) bad = 1;

	p[y] = x;
}

int main(){
//	freopen("1.in","r",stdin);
//	freopen("1.out","w",stdout);
	cin >> n;
	for (int i = 0; i < n - 1; i++) {
		scanf("%d%d%d", &q[i].S.F, &q[i].S.S, &q[i].F);
		q[i].S.F--;
		q[i].S.S--;
	}
	sort(q, q + n - 1);
	int ans = 0;
	bad = 0;
	for (int i = 0; i < n; i++) {
		p[i] = i;
		scanf("%d", &sz[i]);
		kol[i] = 1;
		sum += sz[i];
	}
	for (int i = 0; i < n; i++) if (kol[i] > sum - sz[i]) bad = 1;
	if (bad == 0 && n > 1) ans = q[0].F;
	for (int i = 0; i < n - 1; ) {
		int j = i;
		while (j < n && q[j].F == q[i].F) {
			unite(q[j].S.F, q[j].S.S);
			j++;
		}
		i = j;
		if (bad == 0 && i < n) ans = q[i].F;
		if(bad) break;
	}
	cout << ans << endl;
	return 0;
}


#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 3010;

struct edge{
	int u, v, w;
}e[N];

int n, a[N], f[N], sz[N], t[N], sum;

int getf(int x){
	if(f[x] == x) return x;
	else return f[x] = getf(f[x]);
}

bool check(int x){
	for(int i = 1; i <= n; i++){
		f[i] = i; sz[i] = 1; t[i] = a[i];
	}
	for(int i = 1; i < n; i++){
		if(e[i].w < x){
			int u = e[i].u, v = e[i].v;
			u = getf(u); v = getf(v);
			t[u] += t[v]; sz[u] += sz[v];
			f[v] = u;
		}
	}
	for(int i = 1; i <= n; i++){
		if(f[i] == i && sum - t[i] < sz[i]) return false;
	}
	return true;
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i < n; i++)
		scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
	for(int i = 1; i <= n; i++)
		scanf("%d", &a[i]), sum += a[i];

	int lb = 0, rb = 10000;
	while(lb + 1 < rb){
		int mid  = lb + rb >> 1;
		if(check(mid)) lb = mid; else rb = mid;
	}
	printf("%d\n", lb);
}


#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define LL  long long
#define oo  (1<<30)
using namespace std;

struct edge{int s,t,d;}e[3010];
int n,sum,p[3010],s[3010],x[3010];

bool cmp(edge x,edge y){return x.d<y.d;}
int find(int x){return p[x]==x?x:p[x]=find(p[x]);}

void work()
{
    scanf("%d",&n);
    for (int i=1; i<n; i++)  scanf("%d %d %d",&e[i].s,&e[i].t,&e[i].d);
    sort(e+1,e+n,cmp);
    for (int i=1; i<=n; i++)
        scanf("%d",&x[i]),sum+=x[i],p[i]=i,s[i]=1;
    for (int i=1,a,b; i<n; i++)
        {
            a=find(e[i].s),b=find(e[i].t);
            p[b]=a,s[a]+=s[b],x[a]+=x[b];
            if (s[a]>sum-x[a])  {printf("%d",e[i].d);  return;}
        }
    printf("0");
}

int main()
{
    work();
    return 0;
}


#include<stdio.h>
#include<algorithm>
using namespace std;
struct edge{
	int a,b,v;
}e[3010];
int fa[3010],siz[3010],cnt[3010],sum;
bool can;
bool operator<(edge a,edge b){
	return a.v<b.v;
}
int getfa(int x){
	if(fa[x]==x)return x;
	return fa[x]=getfa(fa[x]);
}
void merge(int x,int y){
	x=getfa(x);
	y=getfa(y);
	siz[x]+=siz[y];
	cnt[x]+=cnt[y];
	fa[y]=x;
	if(siz[x]>sum-cnt[x])can=0;
}
int main(){
	int n,i,ans;
	scanf("%d",&n);
	for(i=1;i<n;i++)scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].v);
	for(i=1;i<=n;i++){
		scanf("%d",cnt+i);
		sum+=cnt[i];
		siz[i]=1;
		fa[i]=i;
	}
	sort(e+1,e+n);
	ans=0;
	can=1;
	for(i=1;i<n;i++){
		if(can)ans=e[i].v;
		merge(e[i].a,e[i].b);
	}
	printf("%d",ans);
}


#include<iostream>
#include<cmath>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;

struct node{
       int x,y,num;
       };

node e[3001];

int n;
int ans=0;
int father[3001];
int s[3001];
int outlet[3001];
int sum_out=0;

bool cmp1(node xx,node yy)
{
    return xx.num<yy.num;
}

int find(int x)
{
    if(father[x]!=x)
    {
        father[x]=find(father[x]);
    }
    return father[x];
}

void unionset(int x,int y)
{
    father[x]=y;
    s[y]+=s[x];
    outlet[y]+=outlet[x];
    return ;
}

int main()
{
    int i,j,k;
    int xx,yy;

    cin>>n;
    for(i=1;i<=n-1;i++)
    {
        cin>>e[i].x>>e[i].y>>e[i].num;
    }
    sort(e+1,e+n,cmp1);

    for(i=1;i<=n;i++)
    {
        father[i]=i;
        s[i]=1;
        cin>>outlet[i];
        sum_out+=outlet[i];
    }

    if(n==1)
    {
        cout<<0<<endl;
        return 0;
    }

    ans=e[1].num;
    for(i=1;i<=n-2;i++)
    {
        xx=find(e[i].x);
        yy=find(e[i].y);

        unionset(xx,yy);

        if(sum_out-outlet[yy]<s[yy])
        {
            break;
        }
        else
        {
           ans=e[i+1].num;
        }
    }

    cout<<ans<<endl;

    return 0;
}


#include<iostream>
#include<cmath>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;

struct node{
       int x,y,num;
       };

node e[3001];

int n;
int ans=0;
int father[3001];
int s[3001];
int outlet[3001];
int sum_out=0;

bool cmp1(node xx,node yy)
{
    return xx.num<yy.num;
}

int find(int x)
{
    if(father[x]!=x)
    {
        father[x]=find(x);
    }
    return father[x];
}

void unionset(int x,int y)
{
    father[x]=y;
    s[y]+=s[x];
    outlet[y]+=outlet[x];
    return ;
}

int main()
{
    int i,j,k;
    int xx,yy;

    cin>>n;
    for(i=1;i<=n-1;i++)
    {
        cin>>e[i].x>>e[i].y>>e[i].num;
    }
    sort(e+1,e+n,cmp1);

    for(i=1;i<=n;i++)
    {
        father[i]=i;
        s[i]=1;
        cin>>outlet[i];
        sum_out+=outlet[i];
    }

    if(n==1)
    {
        cout<<0<<endl;
        return 0;
    }

    ans=e[1].num;
    for(i=1;i<=n-2;i++)
    {
        xx=find(e[i].x);
        yy=find(e[i].y);

        unionset(xx,yy);

        if(sum_out-outlet[yy]<s[yy])
        {
            break;
        }
        else
        {
           ans=e[i+1].num;
        }
    }

    cout<<ans<<endl;

    return 0;
}


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3005;
struct data{
	int x,y,w;
}a[N];
int n,f[N],x[N],sz[N];
bool cmp(const data &p,const data &q){
	return p.w<q.w;
}
int find(int x){return f[x]==x?f[x]:find(f[x]);}
int main(){
	scanf("%d",&n);
	for(int i=1;i<n;++i)	scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
	sort(a+1,a+n,cmp);
	int sum=0;
	for(int i=1;i<=n;++i){
		scanf("%d",&x[i]);
		sum+=x[i];
		f[i]=i;
		sz[i]=1;
	}
	bool f=false;
	for(int i=1;i<n;++i){
		int fx=find(a[i].x),fy=find(a[i].y);
		f[fx]=fy,x[fy]+=x[fx],sz[fy]+=sz[fx];
		if(sz[fy]>sum-x[fy]){
			printf("%d\n",a[i].w);
			f=true;
			break;
		}
	}
	if(!f)	puts("0");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=3005;
struct data{
	int x,y,w;
}a[N];
int n,f[N],x[N],sz[N];
bool cmp(const data &p,const data &q){
	return p.w<q.w;
}
int find(int x){return f[x]==x?f[x]:find(f[x]);}
int main(){
	scanf("%d",&n);
	for(int i=1;i<n;++i)	scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
	sort(a+1,a+n,cmp);
	int sum=0;
	for(int i=1;i<=n;++i){
		scanf("%d",&x[i]);
		sum+=x[i];
		f[i]=i;
		sz[i]=1;
	}
	for(int i=1;i<n;++i){
		int fx=find(a[i].x),fy=find(a[i].y);
		f[fx]=fy,x[fy]+=x[fx],sz[fy]+=sz[fx];
		if(sz[fy]>sum-x[fy]){
			printf("%d\n",a[i].w);
			break;
		}
	}
	return 0;
}


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3005;
struct data{
	int x,y,w;
}a[N];
int n,f[N],x[N],sz[N];
bool cmp(const data &p,const data &q){
	return p.w<q.w;
}
int find(int x){return f[x]==x?f[x]:find(f[x]);}
int main(){
	scanf("%d",&n);
	for(int i=1;i<n;++i)	scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
	sort(a+1,a+n,cmp);
	int sum=0;
	for(int i=1;i<=n;++i){
		scanf("%d",&x[i]);
		sum+=x[i];
		f[i]=i;
		sz[i]=1;
	}
	bool flag=false;
	for(int i=1;i<n;++i){
		int fx=find(a[i].x),fy=find(a[i].y);
		f[fx]=fy,x[fy]+=x[fx],sz[fy]+=sz[fx];
		if(sz[fy]>sum-x[fy]){
			printf("%d\n",a[i].w);
			flag=true;
			break;
		}
	}
	if(!flag)	puts("0");
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int fa[100001],size[100001],data[100001];
int n,sum,ans;
struct rec{int x,y,z;}E[100001];
bool cmp(rec a,rec b){return a.z<b.z;}
int getfa(int v){
	if(fa[v]==v) return v;
	int f=fa[v];
	fa[v]=getfa(fa[v]);
//	size[f]+=size[v];
//	data[f]+=data[v];
	return fa[v];
}
int main(){
	scanf("%d",&n);
	for (int i=1;i<n;i++) scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].z);
	for (int i=1;i<=n;i++){
		scanf("%d",&data[i]),size[i]=1,fa[i]=i;
		sum+=data[i];
	}
	if(sum<n){printf("0\n"); return 0;}
	sort(E+1,E+n,cmp); ans=E[1].z;
	for (int i=1;i<n-1;i++){
		int x,y;
		x=getfa(E[i].x);
		y=getfa(E[i].y);
		fa[y]=x;
		size[x]+=size[y];
		data[x]+=data[y];
	//	printf("size[%d] %d\n",x,size[x]);
		if(size[x]<=sum-data[x]&&data[x]>=n-size[x]) ans=E[i+1].z;
	}
	printf("%d\n",ans);
}


#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int fa[100001],size[100001],data[100001];
int n,sum,ans;
struct rec{int x,y,z;}E[100001];
bool cmp(rec a,rec b){return a.z<b.z;}
int getfa(int v){
	if(fa[v]==v) return v;
	int f=fa[v];
	fa[v]=getfa(fa[v]);
//	size[f]+=size[v];
//	data[f]+=data[v];
	return fa[v];
}
int main(){
	scanf("%d",&n);
	for (int i=1;i<n;i++) scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].z);
	for (int i=1;i<=n;i++){
		scanf("%d",&data[i]),size[i]=1,fa[i]=i;
		sum+=data[i];
	}
	if(sum<n){printf("0\n"); return 0;}
	sort(E+1,E+n,cmp); ans=E[1].z;
	for (int i=1;i<n-1;i++){
		int x,y;
		x=getfa(E[i].x);
		y=getfa(E[i].y);
		fa[y]=x;
		size[x]+=size[y];
		data[x]+=data[y];
	//	printf("size[%d] %d\n",x,size[x]);
		if(size[x]<=sum-data[x]) ans=E[i+1].z;
	}
	printf("%d\n",ans);
}


#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int fa[100001],size[100001],data[100001];
int n,sum,ans;
struct rec{int x,y,z;}E[100001];
bool cmp(rec a,rec b){return a.z<b.z;}
int getfa(int v){
	if(fa[v]==v) return v;
	int f=fa[v];
	fa[v]=getfa(fa[v]);
//	size[f]+=size[v];
//	data[f]+=data[v];
	return fa[v];
}
int main(){
	scanf("%d",&n);
	for (int i=1;i<n;i++) scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].z);
	for (int i=1;i<=n;i++){
		scanf("%d",&data[i]),size[i]=1,fa[i]=i;
		sum+=data[i];
	}
	if(sum<n){printf("0\n"); return 0;}
	sort(E+1,E+n,cmp); ans=E[1].z;
	for (int i=1;i<n-1;i++){
		int x,y;
		x=getfa(E[i].x);
		y=getfa(E[i].y);
		fa[y]=x;
		size[x]+=size[y];
		data[x]+=data[y];
	//	printf("size[%d] %d\n",x,size[x]);
		if(size[x]<=sum-data[x]) ans=E[i+1].z;
		else break;
	}
	printf("%d\n",ans);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#define LL long long
using namespace std;
struct edge
{
	int next,other,va;
}e[18020010];
int dfn[6010],head[6010],tot,x,y,z,f[15][6010],fa[15][3010],L[15][3010],dep[3010],cnt,fr[3010],g[3010][3010],n;
bool vis[3010];
int a[3010],S,T,dis[6010],di[6010],pre[6010],ans,his[6010],vh[6010],inf=100000000;
void read(int &x)
{
	char ch=getchar();int mark=1;for(;ch!='-'&&(ch<'0'||ch>'9');ch=getchar());if (ch=='-') mark=-1,ch=getchar();
	for(x=0;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-48;x*=mark;
}
inline void add(int x,int y,int z)
{
	e[++tot].next=head[x];head[x]=tot;e[tot].other=y;e[tot].va=z;
}
void dfs(int u)
{
	vis[u]=1;dfn[++cnt]=u;fr[u]=cnt;
	for(int i=head[u];i;i=e[i].next)
	{
		int v=e[i].other;
		if (!vis[v])
		{
			fa[0][v]=u;L[0][v]=e[i].va;dep[v]=dep[u]+1;dfs(v);dfn[++cnt]=u;
		}
	}
}
inline int Get(int x){int ans=-1;while (x){x>>=1;ans++;};return ans;}
void prepare()
{
	for(int i=1;i<=cnt;i++) f[0][i]=dep[dfn[i]];
	int t=Get(cnt);
	for(int i=1;i<=t;i++)
		for(int j=1;j+(1<<i)-1<=cnt;j++)
			f[i][j]=min(f[i-1][j],f[i-1][j+(1<<(i-1))]);
	for(int i=1;i<=t;i++)
		for(int j=1;j<=n;j++)
		{
			fa[i][j]=fa[i-1][fa[i-1][j]];
			L[i][j]=max(L[i-1][j],L[i-1][fa[i-1][j]]);
		}
}
int Getlca(int x,int y)
{
	x=fr[x];y=fr[y];
	if (x>y) swap(x,y);
	int t=Get(y-x+1);
	return min(f[t][x],f[t][y-(1<<t)+1]);
}
int Getlen(int u,int l)
{
	int ans=0,t=0;
	while (l)
	{
		if (l&1)
		{
			ans=max(ans,L[t][u]);u=fa[t][u];
		}
		l>>=1;t++;
	}
	return ans;
}
void flow()
{
	for(int i=S;i<=T;i++) di[i]=head[i];
	vh[0]=T;int u=S,aug=inf;
	while (dis[S]<T)
	{
		bool flag=0;his[u]=aug;
		for(int i=di[u];i;i=e[i].next)
		{
			int v=e[i].other;
			if (e[i].va>0&&dis[u]==dis[v]+1)
			{
				pre[v]=di[u]=i;flag=1;aug=min(aug,e[i].va);u=v;
				if (u==T)
				{
					ans+=aug;
					for(;u!=S;u=e[pre[u]^1].other)
					{
						e[pre[u]].va-=aug;
						e[pre[u]^1].va+=aug;
					}
					aug=inf;
				}
				break;
			}
		}
		if (flag) continue;
		if (--vh[dis[u]]==0) break;
		int Min=T,j;
		for(int i=head[u];i;i=e[i].next)
		{
			int v=e[i].other;
			if (e[i].va>0&&dis[v]<Min)
			{
				Min=dis[v];j=i;
			}
		}
		vh[dis[u]=Min+1]++;di[u]=j;
		if (u!=S)
		{
			u=e[pre[u]^1].other;aug=his[u];
		}
	}
}
bool check(int mid)
{
	S=1;T=n*2+2;tot=1;
	for(int i=S;i<=T;i++) head[i]=dis[i]=vh[i]=0;
	for(int i=1;i<=n;i++)
	{
		add(S,i+1,a[i]);add(i+1,S,0);
		for(int j=1;j<=n;j++)
			if (g[i][j]>=mid) add(j+1,i+n+1,inf),add(i+n+1,j+1,0);
		add(i+n+1,T,1);add(T,i+n+1,0);
	}
	ans=0;
	flow();
	return ans==n;
}
int main()
{
	read(n);
	int l=1,r=0;
	for(int i=1;i<n;i++)
	{
		read(x);read(y);read(z);
		add(x,y,z);add(y,x,z);
		r=max(r,z);
	}
	dfs(1);
	prepare();
	for(int i=1;i<=n;i++)
		for(int j=1;j<i;j++)
		{
			int t=Getlca(i,j);
			g[i][j]=g[j][i]=max(Getlen(i,dep[i]-t),Getlen(j,dep[j]-t));
			//printf("%d %d %d\n",i,j,g[i][j]);
		}
	for(int i=1;i<=n;i++) read(a[i]);
	while (l+1<r)
	{
		int mid=(l+r)>>1;
		if (check(mid)) l=mid;
		else r=mid;
	}
	if (check(r)) printf("%d\n",r);else printf("%d\n",l);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#define LL long long
using namespace std;
struct edge
{
	int next,other,va;
}e[9000010];
int dfn[6010],head[6010],tot,x,y,z,f[15][6010],fa[15][3010],L[15][3010],dep[3010],cnt,fr[3010],g[3010][3010],n;
bool vis[3010];
int a[3010],S,T,dis[6010],di[6010],pre[6010],ans,his[6010],vh[6010],inf=100000000;
void read(int &x)
{
	char ch=getchar();int mark=1;for(;ch!='-'&&(ch<'0'||ch>'9');ch=getchar());if (ch=='-') mark=-1,ch=getchar();
	for(x=0;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-48;x*=mark;
}
inline void add(int x,int y,int z)
{
	e[++tot].next=head[x];head[x]=tot;e[tot].other=y;e[tot].va=z;
}
void dfs(int u)
{
	vis[u]=1;dfn[++cnt]=u;fr[u]=cnt;
	for(int i=head[u];i;i=e[i].next)
	{
		int v=e[i].other;
		if (!vis[v])
		{
			fa[0][v]=u;L[0][v]=e[i].va;dep[v]=dep[u]+1;dfs(v);dfn[++cnt]=u;
		}
	}
}
inline int Get(int x){int ans=-1;while (x){x>>=1;ans++;};return ans;}
void prepare()
{
	for(int i=1;i<=cnt;i++) f[0][i]=dep[dfn[i]];
	int t=Get(cnt);
	for(int i=1;i<=t;i++)
		for(int j=1;j+(1<<i)-1<=cnt;j++)
			f[i][j]=min(f[i-1][j],f[i-1][j+(1<<(i-1))]);
	for(int i=1;i<=t;i++)
		for(int j=1;j<=n;j++)
		{
			fa[i][j]=fa[i-1][fa[i-1][j]];
			L[i][j]=max(L[i-1][j],L[i-1][fa[i-1][j]]);
		}
}
int Getlca(int x,int y)
{
	x=fr[x];y=fr[y];
	if (x>y) swap(x,y);
	int t=Get(y-x+1);
	return min(f[t][x],f[t][y-(1<<t)+1]);
}
int Getlen(int u,int l)
{
	int ans=0,t=0;
	while (l)
	{
		if (l&1)
		{
			ans=max(ans,L[t][u]);u=fa[t][u];
		}
		l>>=1;t++;
	}
	return ans;
}
void flow()
{
	for(int i=S;i<=T;i++) di[i]=head[i];
	vh[0]=T;int u=S,aug=inf;
	while (dis[S]<T)
	{
		bool flag=0;his[u]=aug;
		for(int i=di[u];i;i=e[i].next)
		{
			int v=e[i].other;
			if (e[i].va>0&&dis[u]==dis[v]+1)
			{
				pre[v]=di[u]=i;flag=1;aug=min(aug,e[i].va);u=v;
				if (u==T)
				{
					ans+=aug;
					for(;u!=S;u=e[pre[u]^1].other)
					{
						e[pre[u]].va-=aug;
						e[pre[u]^1].va+=aug;
					}
					aug=inf;
				}
				break;
			}
		}
		if (flag) continue;
		if (--vh[dis[u]]==0) break;
		int Min=T,j;
		for(int i=head[u];i;i=e[i].next)
		{
			int v=e[i].other;
			if (e[i].va>0&&dis[v]<Min)
			{
				Min=dis[v];j=i;
			}
		}
		vh[dis[u]=Min+1]++;di[u]=j;
		if (u!=S)
		{
			u=e[pre[u]^1].other;aug=his[u];
		}
	}
}
bool check(int mid)
{
	S=1;T=n*2+2;tot=1;
	for(int i=S;i<=T;i++) head[i]=dis[i]=vh[i]=0;
	for(int i=1;i<=n;i++)
	{
		add(S,i+1,a[i]);add(i+1,S,0);
		for(int j=1;j<=n;j++)
			if (g[i][j]>=mid) add(j+1,i+n+1,inf),add(i+n+1,j+1,0);
		add(i+n+1,T,1);add(T,i+n+1,0);
	}
	ans=0;
	flow();
	return ans==n;
}
int main()
{
	read(n);
	int l=1,r=0;
	for(int i=1;i<n;i++)
	{
		read(x);read(y);read(z);
		add(x,y,z);add(y,x,z);
		r=max(r,z);
	}
	dfs(1);
	prepare();
	for(int i=1;i<=n;i++)
		for(int j=1;j<i;j++)
		{
			int t=Getlca(i,j);
			g[i][j]=g[j][i]=max(Getlen(i,dep[i]-t),Getlen(j,dep[j]-t));
			//printf("%d %d %d\n",i,j,g[i][j]);
		}
	for(int i=1;i<=n;i++) read(a[i]);
	while (l+1<r)
	{
		int mid=(l+r)>>1;
		if (check(mid)) l=mid;
		else r=mid;
	}
	if (check(r)) printf("%d\n",r);else printf("%d\n",l);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#define LL long long
using namespace std;
struct edge
{
	int next,other,va;
}e[6010];
int dfn[6010],head[6010],tot,x,y,z,f[15][6010],fa[15][3010],L[15][3010],dep[3010],cnt,fr[3010],g[3010][3010],n;
bool vis[3010];
int a[3010],S,T,dis[6010],di[6010],pre[6010],ans,his[6010],vh[6010],inf=100000000;
void read(int &x)
{
	char ch=getchar();int mark=1;for(;ch!='-'&&(ch<'0'||ch>'9');ch=getchar());if (ch=='-') mark=-1,ch=getchar();
	for(x=0;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-48;x*=mark;
}
inline void add(int x,int y,int z)
{
	e[++tot].next=head[x];head[x]=tot;e[tot].other=y;e[tot].va=z;
}
void dfs(int u)
{
	vis[u]=1;dfn[++cnt]=u;fr[u]=cnt;
	for(int i=head[u];i;i=e[i].next)
	{
		int v=e[i].other;
		if (!vis[v])
		{
			fa[0][v]=u;L[0][v]=e[i].va;dep[v]=dep[u]+1;dfs(v);dfn[++cnt]=u;
		}
	}
}
inline int Get(int x){int ans=-1;while (x){x>>=1;ans++;};return ans;}
void prepare()
{
	for(int i=1;i<=cnt;i++) f[0][i]=dep[dfn[i]];
	int t=Get(cnt);
	for(int i=1;i<=t;i++)
		for(int j=1;j+(1<<i)-1<=cnt;j++)
			f[i][j]=min(f[i-1][j],f[i-1][j+(1<<(i-1))]);
	for(int i=1;i<=t;i++)
		for(int j=1;j<=n;j++)
		{
			fa[i][j]=fa[i-1][fa[i-1][j]];
			L[i][j]=max(L[i-1][j],L[i-1][fa[i-1][j]]);
		}
}
int Getlca(int x,int y)
{
	x=fr[x];y=fr[y];
	if (x>y) swap(x,y);
	int t=Get(y-x+1);
	return min(f[t][x],f[t][y-(1<<t)+1]);
}
int Getlen(int u,int l)
{
	int ans=0,t=0;
	while (l)
	{
		if (l&1)
		{
			ans=max(ans,L[t][u]);u=fa[t][u];
		}
		l>>=1;t++;
	}
	return ans;
}
void flow()
{
	for(int i=S;i<=T;i++) di[i]=head[i];
	vh[0]=T;int u=S,aug=inf;
	while (dis[S]<T)
	{
		bool flag=0;his[u]=aug;
		for(int i=di[u];i;i=e[i].next)
		{
			int v=e[i].other;
			if (e[i].va>0&&dis[u]==dis[v]+1)
			{
				pre[v]=di[u]=i;flag=1;aug=min(aug,e[i].va);u=v;
				if (u==T)
				{
					ans+=aug;
					for(;u!=S;u=e[pre[u]^1].other)
					{
						e[pre[u]].va-=aug;
						e[pre[u]^1].va+=aug;
					}
					aug=inf;
				}
				break;
			}
		}
		if (flag) continue;
		if (--vh[dis[u]]==0) break;
		int Min=T,j;
		for(int i=head[u];i;i=e[i].next)
		{
			int v=e[i].other;
			if (e[i].va>0&&dis[v]<Min)
			{
				Min=dis[v];j=i;
			}
		}
		vh[dis[u]=Min+1]++;di[u]=j;
		if (u!=S)
		{
			u=e[pre[u]^1].other;aug=his[u];
		}
	}
}
bool check(int mid)
{
	S=1;T=n*2+2;tot=1;
	for(int i=S;i<=T;i++) head[i]=dis[i]=vh[i]=0;
	for(int i=1;i<=n;i++)
	{
		add(S,i+1,a[i]);add(i+1,S,0);
		for(int j=1;j<=n;j++)
			if (g[i][j]>=mid) add(j+1,i+n+1,inf),add(i+n+1,j+1,0);
		add(i+n+1,T,1);add(T,i+n+1,0);
	}
	ans=0;
	flow();
	return ans==n;
}
int main()
{
	read(n);
	int l=1,r=0;
	for(int i=1;i<n;i++)
	{
		read(x);read(y);read(z);
		add(x,y,z);add(y,x,z);
		r=max(r,z);
	}
	dfs(1);
	prepare();
	for(int i=1;i<=n;i++)
		for(int j=1;j<i;j++)
		{
			int t=Getlca(i,j);
			g[i][j]=g[j][i]=max(Getlen(i,dep[i]-t),Getlen(j,dep[j]-t));
			//printf("%d %d %d\n",i,j,g[i][j]);
		}
	for(int i=1;i<=n;i++) read(a[i]);
	while (l+1<r)
	{
		int mid=(l+r)>>1;
		if (check(mid)) l=mid;
		else r=mid;
	}
	if (check(r)) printf("%d\n",r);else printf("%d\n",l);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#define LL long long
using namespace std;
struct edge
{
	int x,y,z;
}p[3010];
int x,y,z,f[3010],n,a[3010],size[3010],sum;
bool can;
void read(int &x)
{
	char ch=getchar();int mark=1;for(;ch!='-'&&(ch<'0'||ch>'9');ch=getchar());if (ch=='-') mark=-1,ch=getchar();
	for(x=0;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-48;x*=mark;
}
inline bool cmp(edge A,edge B){return A.z<B.z;}
int find(int x){return (f[x]==x)?x:f[x]=find(f[x]);}
void Union(int x,int y)
{
	int u=find(x),v=find(y);
	f[v]=f[u];
	size[u]+=size[v];
	a[u]+=a[v];
	if (size[u]>sum-a[u]) can=0;
}
int main()
{
	read(n);
	for(int i=1;i<n;i++)
	{
		read(p[i].x);read(p[i].y);read(p[i].z);
	}
	sort(p+1,p+n,cmp);
	sum=0;
	for(int i=1;i<=n;i++)
	{
		f[i]=i;read(a[i]);
		size[i]=1;sum+=a[i];
	}
	int ans=0;
	can=1;
	for(int i=1;i<=n;i++)
		if (size[i]>sum-a[i])
		{
			can=0;break;
		}
	if (can&&n>1) ans=p[1].z;
	for(int i=1;i<n;)
	{
		int j=i;
		if (!can) break;
		for(;j<n&&p[j].z==p[i].z;j++)
		{
			if (find(p[j].x)!=find(p[j].y)) Union(p[j].x,p[j].y);
		}
		i=j;
		if (can&&i<n) ans=p[i].z;
	}
	printf("%d\n",ans);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e3+5;
int n;
struct UNIT{
	int id,value;
	inline bool operator <(const UNIT &tmp)const{
		return value>tmp.value;
	}
}val[N][N];
struct Tree{
	static const int LG=13;
	int tot_edge,head[N],dep[N],par[N][LG],mx[N][LG];
	struct Edge{
		int to,nxt,cost;
	}edge[N<<1];
	inline void add_edge(int from,int to,int c){
		edge[tot_edge]=(Edge){to,head[from],c};
		head[from]=tot_edge++;
	}
	inline void Max(int &a,int b){
		if(b>a)a=b;
	}
	void dfs(int cur,int fa,int depth,int pre_cost){
		dep[cur]=depth++;
		par[cur][0]=fa;
		mx[cur][0]=pre_cost;
		for(int i=1;i<LG;++i){
			par[cur][i]=par[par[cur][i-1]][i-1];
			mx[cur][i]=max(mx[cur][i-1],mx[par[cur][i-1]][i-1]);
		}
		for(int i=head[cur];~i;i=edge[i].nxt){
			int to=edge[i].to;
			if(to==fa)continue;
			dfs(to,cur,depth,edge[i].cost);
		}
	}
	int up(int cur,int step){
		for(int i=0;i<LG;++i)
			if(step&1<<i)
				cur=par[cur][i];
		return cur;
	}
	int up_mx(int cur,int step){
		int res=0;
		for(int i=0;i<LG;++i)
			if(step&1<<i){
				Max(res,mx[cur][i]);
				cur=par[cur][i];
			}
		return res;
	}
	int lca(int u,int v){
		if(dep[u]<dep[v])swap(u,v);
		u=up(u,dep[u]-dep[v]);
		if(u==v)return u;
		for(int i=LG-1;~i;--i)
			if(par[u][i]!=par[v][i]){
				u=par[u][i];
				v=par[v][i];
			}
		return par[u][0];
	}
	int query_mx(int u,int v){
		int anc=lca(u,v);
		return max(up_mx(u,dep[u]-dep[anc]),up_mx(v,dep[v]-dep[anc]));
	}
	void solve(){
		tot_edge=0;
		memset(head,-1,sizeof(head));
		for(int i=1,u,v,c;i<n;++i){
			scanf("%d%d%d",&u,&v,&c);
			add_edge(u,v,c);
			add_edge(v,u,c);
		}
		for(int i=0;i<LG;++i)
			par[0][i]=mx[0][i]=0;
		dfs(1,0,0,0);
		for(int i=1;i<=n;++i){
			for(int j=1;j<=n;++j)
				val[i][j]=(UNIT){j,query_mx(i,j)};
			sort(val[i]+1,val[i]+n+1);
		}
	}
}T;
struct Network{
	static const int C=1e4,V=N<<1,E=N*N+(N<<1),INF=0x7fffffff;
	int src,sink,tot_edge,lim[N],head[V],dist[V],arc[V],que[V];
	bool used[V];
	struct Edge{
		int to,nxt,cap;
	}edge[E<<1];
	inline void add_edge(int from,int to,int c){
		edge[tot_edge]=(Edge){to,head[from],c};
		head[from]=tot_edge++;
		edge[tot_edge]=(Edge){from,head[to],0};
		head[to]=tot_edge++;
	}
	void bfs(){
		int L=0,R=0;
		for(int i=src;i<=sink;++i)
			dist[i]=-1;
		dist[que[R++]=src]=0;
		while(L<R){
			int cur=que[L++];
			for(int i=head[cur];~i;i=edge[i].nxt){
				int to=edge[i].to;
				if(edge[i].cap&&dist[to]==-1){
					dist[to]=dist[cur]+1;
					que[R++]=to;
				}
			}
		}
	}
	int dfs(int cur,int f){
		if(cur==sink)return f;
		used[cur]=true;
		for(int &i=arc[cur];~i;i=edge[i].nxt){
			int to=edge[i].to;
			if(!used[to]&&edge[i].cap&&dist[to]==dist[cur]+1){
				int d=dfs(to,min(f,edge[i].cap));
				if(d){
					edge[i].cap-=d;
					edge[i^1].cap+=d;
					return d;
				}
			}
		}
		return 0;
	}
	int Dinic(){
		int flow=0;
		while(true){
			bfs();
			if(dist[sink]==-1)return flow;
			for(int i=src;i<=sink;++i)
				arc[i]=head[i];
			while(true){
				memset(used,false,sink+1);
				int f=dfs(src,INF);
				if(!f)break;
				flow+=f;
			}
		}
	}
	bool judge(int limit){
		tot_edge=0;
		memset(head,-1,sink+1<<2);
		for(int i=1;i<=n;++i){
			add_edge(src,i,lim[i]);
			add_edge(n+i,sink,1);
			for(int j=1;j<=n;++j){
				if(val[i][j].value<limit)break;
				add_edge(i,n+val[i][j].id,1);
			}
		}
		return Dinic()==n;
	}
	void solve(){
		for(int i=1;i<=n;++i)
			scanf("%d",&lim[i]);
		src=0;
		sink=(n<<1)+1;
		int L=0,R=C,ans;
		while(L<=R){
			int mid=L+R>>1;
			if(judge(mid)){
				ans=mid;
				L=mid+1;
			}
			else R=mid-1;
		}
		printf("%d\n",ans);
	}
}network;
int main(){
	scanf("%d",&n);
	T.solve();
	network.solve();
	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int N=3e3+5;
int n;
struct UNIT{
	int id,value;
	inline bool operator <(const UNIT &tmp)const{
		return value>tmp.value;
	}
}val[N][N];
struct Tree{
	static const int LG=13;
	int tot_edge,head[N],dep[N],par[N][LG],mx[N][LG];
	struct Edge{
		int to,nxt,cost;
	}edge[N<<1];
	inline void add_edge(int from,int to,int c){
		edge[tot_edge]=(Edge){to,head[from],c};
		head[from]=tot_edge++;
	}
	inline void Max(int &a,int b){
		if(b>a)a=b;
	}
	void dfs(int cur,int fa,int depth,int pre_cost){
		dep[cur]=depth++;
		par[cur][0]=fa;
		mx[cur][0]=pre_cost;
		for(int i=1;i<LG;++i){
			par[cur][i]=par[par[cur][i-1]][i-1];
			mx[cur][i]=max(mx[cur][i-1],mx[par[cur][i-1]][i-1]);
		}
		for(int i=head[cur];~i;i=edge[i].nxt){
			int to=edge[i].to;
			if(to==fa)continue;
			dfs(to,cur,depth,edge[i].cost);
		}
	}
	int up(int cur,int step){
		for(int i=0;i<LG;++i)
			if(step&1<<i)
				cur=par[cur][i];
		return cur;
	}
	int up_mx(int cur,int step){
		int res=0;
		for(int i=0;i<LG;++i)
			if(step&1<<i){
				Max(res,mx[cur][i]);
				cur=par[cur][i];
			}
		return res;
	}
	int lca(int u,int v){
		if(dep[u]<dep[v])swap(u,v);
		u=up(u,dep[u]-dep[v]);
		if(u==v)return u;
		for(int i=LG-1;~i;--i)
			if(par[u][i]!=par[v][i]){
				u=par[u][i];
				v=par[v][i];
			}
		return par[u][0];
	}
	int query_mx(int u,int v){
		int anc=lca(u,v);
		return max(up_mx(u,dep[u]-dep[anc]),up_mx(v,dep[v]-dep[anc]));
	}
	void solve(){
		tot_edge=0;
		memset(head,-1,sizeof(head));
		for(int i=1,u,v,c;i<n;++i){
			scanf("%d%d%d",&u,&v,&c);
			add_edge(u,v,c);
			add_edge(v,u,c);
		}
		for(int i=0;i<LG;++i)
			par[0][i]=mx[0][i]=0;
		dfs(1,0,0,0);
		for(int i=1;i<=n;++i){
			for(int j=1;j<=n;++j)
				val[i][j]=(UNIT){j,query_mx(i,j)};
			sort(val[i]+1,val[i]+n+1);
		}
	}
}T;
struct Network{
	static const int C=1e4,V=N<<1,E=N*N+(N<<1),INF=0x7fffffff;
	int src,sink,tot_edge,lim[N],head[V],dist[V],arc[V],que[V];
	bool used[V];
	struct Edge{
		int to,nxt,cap;
	};
	vector<Edge>edge;
	inline void add_edge(int from,int to,int c){
		edge.push_back((Edge){to,head[from],c});
		head[from]=tot_edge++;
		edge.push_back((Edge){from,head[to],0});
		head[to]=tot_edge++;
	}
	void bfs(){
		int L=0,R=0;
		for(int i=src;i<=sink;++i)
			dist[i]=-1;
		dist[que[R++]=src]=0;
		while(L<R){
			int cur=que[L++];
			for(int i=head[cur];~i;i=edge[i].nxt){
				int to=edge[i].to;
				if(edge[i].cap&&dist[to]==-1){
					dist[to]=dist[cur]+1;
					que[R++]=to;
				}
			}
		}
	}
	int dfs(int cur,int f){
		if(cur==sink)return f;
		used[cur]=true;
		for(int &i=arc[cur];~i;i=edge[i].nxt){
			int to=edge[i].to;
			if(!used[to]&&edge[i].cap&&dist[to]==dist[cur]+1){
				int d=dfs(to,min(f,edge[i].cap));
				if(d){
					edge[i].cap-=d;
					edge[i^1].cap+=d;
					return d;
				}
			}
		}
		return 0;
	}
	int Dinic(){
		int flow=0;
		while(true){
			bfs();
			if(dist[sink]==-1)return flow;
			for(int i=src;i<=sink;++i)
				arc[i]=head[i];
			while(true){
				memset(used,false,sink+1);
				int f=dfs(src,INF);
				if(!f)break;
				flow+=f;
			}
		}
	}
	bool judge(int limit){
		tot_edge=0;
		edge.clear();
		memset(head,-1,sink+1<<2);
		for(int i=1;i<=n;++i){
			add_edge(src,i,lim[i]);
			add_edge(n+i,sink,1);
			for(int j=1;j<=n;++j){
				if(val[i][j].value<limit)break;
				add_edge(i,n+val[i][j].id,1);
			}
		}
		return Dinic()==n;
	}
	void solve(){
		for(int i=1;i<=n;++i)
			scanf("%d",&lim[i]);
		src=0;
		sink=(n<<1)+1;
		int L=0,R=C,ans;
		while(L<=R){
			int mid=L+R>>1;
			if(judge(mid)){
				ans=mid;
				L=mid+1;
			}
			else R=mid-1;
		}
		printf("%d\n",ans);
	}
}network;
int main(){
	scanf("%d",&n);
	T.solve();
	network.solve();
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e3+5;
int n;
struct UNIT{
	short id,value;
	inline bool operator <(const UNIT &tmp)const{
		return value>tmp.value;
	}
}val[N][N];
struct Tree{
	static const int LG=13;
	int tot_edge,head[N],dep[N],par[N][LG],mx[N][LG];
	struct Edge{
		int to,nxt,cost;
	}edge[N<<1];
	inline void add_edge(int from,int to,int c){
		edge[tot_edge]=(Edge){to,head[from],c};
		head[from]=tot_edge++;
	}
	inline void Max(int &a,int b){
		if(b>a)a=b;
	}
	void dfs(int cur,int fa,int depth,int pre_cost){
		dep[cur]=depth++;
		par[cur][0]=fa;
		mx[cur][0]=pre_cost;
		for(int i=1;i<LG;++i){
			par[cur][i]=par[par[cur][i-1]][i-1];
			mx[cur][i]=max(mx[cur][i-1],mx[par[cur][i-1]][i-1]);
		}
		for(int i=head[cur];~i;i=edge[i].nxt){
			int to=edge[i].to;
			if(to==fa)continue;
			dfs(to,cur,depth,edge[i].cost);
		}
	}
	int up(int cur,int step){
		for(int i=0;i<LG;++i)
			if(step&1<<i)
				cur=par[cur][i];
		return cur;
	}
	int up_mx(int cur,int step){
		int res=0;
		for(int i=0;i<LG;++i)
			if(step&1<<i){
				Max(res,mx[cur][i]);
				cur=par[cur][i];
			}
		return res;
	}
	int lca(int u,int v){
		if(dep[u]<dep[v])swap(u,v);
		u=up(u,dep[u]-dep[v]);
		if(u==v)return u;
		for(int i=LG-1;~i;--i)
			if(par[u][i]!=par[v][i]){
				u=par[u][i];
				v=par[v][i];
			}
		return par[u][0];
	}
	int query_mx(int u,int v){
		int anc=lca(u,v);
		return max(up_mx(u,dep[u]-dep[anc]),up_mx(v,dep[v]-dep[anc]));
	}
	void solve(){
		tot_edge=0;
		memset(head,-1,sizeof(head));
		for(int i=1,u,v,c;i<n;++i){
			scanf("%d%d%d",&u,&v,&c);
			add_edge(u,v,c);
			add_edge(v,u,c);
		}
		for(int i=0;i<LG;++i)
			par[0][i]=mx[0][i]=0;
		dfs(1,0,0,0);
		for(int i=1;i<=n;++i){
			for(int j=1;j<=n;++j)
				val[i][j]=(UNIT){j,query_mx(i,j)};
			sort(val[i]+1,val[i]+n+1);
		}
	}
}T;
struct Network{
	static const int C=1e4,V=N<<1,E=N*N+(N<<1);
	static const short INF=32767;
	int src,sink,tot_edge,lim[N],head[V],dist[V],arc[V],que[V];
	bool used[V];
	struct Edge{
		short to,cap;
		int nxt;
	}edge[E<<1];
	inline void add_edge(int from,int to,int c){
		edge[tot_edge]=(Edge){to,c,head[from]};
		head[from]=tot_edge++;
		edge[tot_edge]=(Edge){from,0,head[to]};
		head[to]=tot_edge++;
	}
	void bfs(){
		int L=0,R=0;
		for(int i=src;i<=sink;++i)
			dist[i]=-1;
		dist[que[R++]=src]=0;
		while(L<R){
			int cur=que[L++];
			for(int i=head[cur];~i;i=edge[i].nxt){
				int to=edge[i].to;
				if(edge[i].cap&&dist[to]==-1){
					dist[to]=dist[cur]+1;
					que[R++]=to;
				}
			}
		}
	}
	int dfs(int cur,short f){
		if(cur==sink)return f;
		used[cur]=true;
		for(int &i=arc[cur];~i;i=edge[i].nxt){
			int to=edge[i].to;
			if(!used[to]&&edge[i].cap&&dist[to]==dist[cur]+1){
				int d=dfs(to,min(f,edge[i].cap));
				if(d){
					edge[i].cap-=d;
					edge[i^1].cap+=d;
					return d;
				}
			}
		}
		return 0;
	}
	int Dinic(){
		int flow=0;
		while(true){
			bfs();
			if(dist[sink]==-1)return flow;
			for(int i=src;i<=sink;++i)
				arc[i]=head[i];
			while(true){
				memset(used,false,sink+1);
				int f=dfs(src,INF);
				if(!f)break;
				flow+=f;
			}
		}
	}
	bool judge(int limit){
		tot_edge=0;
		memset(head,-1,sink+1<<2);
		for(int i=1;i<=n;++i){
			add_edge(src,i,lim[i]);
			add_edge(n+i,sink,1);
			for(int j=1;j<=n;++j){
				if(val[i][j].value<limit)break;
				add_edge(i,n+val[i][j].id,1);
			}
		}
		return Dinic()==n;
	}
	void solve(){
		for(int i=1;i<=n;++i)
			scanf("%d",&lim[i]);
		src=0;
		sink=(n<<1)+1;
		int L=0,R=C,ans;
		while(L<=R){
			int mid=L+R>>1;
			if(judge(mid)){
				ans=mid;
				L=mid+1;
			}
			else R=mid-1;
		}
		printf("%d\n",ans);
	}
}network;
int main(){
	scanf("%d",&n);
	T.solve();
	network.solve();
	return 0;
}


#include<cstdio>
#include<algorithm>
using namespace std;
const int N=3e3+5;
int sum,par[N],cnt[N],lim[N];
bool valid;
struct Edge{
	int u,v,cost;
	inline bool operator <(const Edge &tmp)const{
		return cost<tmp.cost;
	}
	void Rd(){
		scanf("%d%d%d",&u,&v,&cost);
	}
}edge[N];
int get_root(int x){
	return par[x]==x?x:par[x]=get_root(par[x]);
}
void unite(int u,int v){
	u=get_root(u);
	v=get_root(v);
	cnt[v]+=cnt[u];
	lim[v]+=lim[u];
	if(cnt[v]>sum-lim[v])valid=false;
	par[u]=v;
}
int main(){
	int n;
	scanf("%d",&n);
	if(n==1){
		puts("0");
		return 0;
	}
	int m=n-1,ans;
	for(int i=0;i<m;++i)
		edge[i].Rd();
	sort(edge,edge+m);
	valid=true;
	sum=0;
	for(int i=1;i<=n;++i){
		cnt[par[i]=i]=1;
		scanf("%d",&lim[i]);
		sum+=lim[i];
	}
	for(int i=0;i<m&&valid;++i){
		if(!i||edge[i].cost!=edge[i-1].cost)ans=edge[i].cost;
		unite(edge[i].u,edge[i].v);
	}
	printf("%d\n",ans);
	return 0;
}


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int size[3010],fa[3010],sum[3010],head[10010];

struct node
{
	int x,y,next;
}e[3010];

int find(int x)
{
	if (x!=fa[x]) fa[x]=find(fa[x]);
	return fa[x];
}

int main()
{
	#ifndef ONLINE_JUDGE
		freopen("input.txt","r",stdin);
		freopen("output.txt","w",stdout);
	#endif
	int n;scanf("%d",&n);
	for (int i=1;i<n;i++)
	{
		int x,y,w;scanf("%d%d%d",&x,&y,&w);
		e[i].x=x;e[i].y=y;e[i].next=head[w];head[w]=i;
	}
	int s=0;
	for (int i=1;i<=n;i++)
	{
		fa[i]=i;size[i]=1;scanf("%d",&sum[i]);s+=sum[i];
	}
	for (int i=1;i<=10000;i++)
	{
		int p=head[i];
		while (p)
		{
			int x=find(e[p].x),y=find(e[p].y);
			fa[y]=x;size[x]+=size[y];sum[x]+=sum[y];
			if (size[x]+sum[x]>s) {printf("%d\n",i);return 0;}
			p=e[p].next;
		}
	}
	puts("0");
	return 0;
}


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int size[3010],fa[3010],sum[3010],head[10010];

struct node
{
	int x,y,next;
}e[3010];

int find(int x)
{
	if (x!=fa[x]) fa[x]=find(fa[x]);
	return fa[x];
}

int main()
{
	#ifndef ONLINE_JUDGE
		freopen("input.txt","r",stdin);
		freopen("output.txt","w",stdout);
	#endif
	int n;scanf("%d",&n);
	for (int i=1;i<n;i++)
	{
		int x,y,w;scanf("%d%d%d",&x,&y,&w);
		e[i].x=x;e[i].y=y;e[i].next=head[w];head[w]=i;
	}
	int s=0;
	for (int i=1;i<=n;i++)
	{
		fa[i]=i;size[i]=1;scanf("%d",&sum[i]);s+=sum[i];
	}
	for (int i=1;i<=10000;i++)
	{
		int p=head[i];
		while (p)
		{
			int x=find(e[p].x),y=find(e[p].y);
			fa[y]=x;size[x]+=size[y];sum[x]+=sum[y];
			if (size[x]+sum[x]>s) {printf("%d\n",i);return 0;}
			p=e[p].next;
		}
	}
	return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define dd c=getchar()
inline int read() {int s=0,w=1;char c;while (dd,c>'9' || c<'0') if (c=='-') w=-1;while (c>='0' && c<='9') s=s*10+c-'0',dd;return s*w;}
#undef dd
const int N=3005;
struct edge {
	int u,t,w;
	bool operator <(edge a) const {
		return w<a.w;
	}
}e[N];
int n,sum,ans;
int X[N],siz[N],fa[N];
int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
vector<pair<int,int> > V;
void merge(int a,int b) {
	fa[b]=a;
	siz[a]+=siz[b];
	X[a]+=X[b];
}
int main() {
	n=read();
	if (n==1) return puts("0");
	for (int i=1;i<n;i++) {
		e[i].u=read(),e[i].t=read(),e[i].w=read();
	}
	sort(e+1,e+n);
	for (int i=1;i<=n;i++) X[i]=read(),sum+=X[i];
	for (int i=1;i<=n;i++) fa[i]=i,siz[i]=1;
	for (int i=1;i<n;i++) {
		int u=find(e[i].u),t=find(e[i].t);
		if (siz[u]>sum-X[u] || siz[t]>sum-X[t]) return printf("%d\n",ans),0;
		ans=e[i].w;
		V.push_back(make_pair(u,t));
		if (e[i].w!=e[i-1].w) {
			for (int j=0;j<(int)V.size();j++) {
				merge(V[j].first,V[j].second);
			}
			V.clear();
		}
	}
	printf("%d\n",ans);
}


#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define dd c=getchar()
inline int read() {int s=0,w=1;char c;while (dd,c>'9' || c<'0') if (c=='-') w=-1;while (c>='0' && c<='9') s=s*10+c-'0',dd;return s*w;}
#undef dd
const int N=3005;
struct edge {
	int u,t,w;
	bool operator <(edge a) const {
		return w<a.w;
	}
}e[N];
int n,sum,ans,can;
int X[N],siz[N],fa[N];
int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
vector<pair<int,int> > V;
void merge(int a,int b) {
	fa[b]=a;
	siz[a]+=siz[b];
	X[a]+=X[b];
	if (siz[a]>sum-X[a]) can=1;
}
int main() {
	n=read();
	if (n==1) return puts("0"),0;
	for (int i=1;i<n;i++) e[i].u=read(),e[i].t=read(),e[i].w=read();
	sort(e+1,e+n);
	for (int i=1;i<=n;i++) X[i]=read(),sum+=X[i];
	for (int i=1;i<=n;i++) fa[i]=i,siz[i]=1;
	for (int i=1;i<n;i++) {
		if (can) break;
		ans=e[i].w;
		int u=find(e[i].u),t=find(e[i].t);
		merge(u,t);
	}
	printf("%d\n",ans);
}


#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define dd c=getchar()
inline int read() {int s=0,w=1;char c;while (dd,c>'9' || c<'0') if (c=='-') w=-1;while (c>='0' && c<='9') s=s*10+c-'0',dd;return s*w;}
#undef dd
const int N=3005;
struct edge {
	int u,t,w;
	bool operator <(edge a) const {
		return w<a.w;
	}
}e[N];
int n,sum,ans;
int X[N],siz[N],fa[N];
int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
vector<pair<int,int>> V;
void merge(int a,int b) {
	fa[b]=a;
	siz[a]+=siz[b];
	X[a]+=X[b];
}
int main() {
	n=read();
	if (n==1) return puts("0");
	for (int i=1;i<n;i++) {
		e[i].u=read(),e[i].t=read(),e[i].w=read();
	}
	sort(e+1,e+n);
	for (int i=1;i<=n;i++) X[i]=read(),sum+=X[i];
	for (int i=1;i<=n;i++) fa[i]=i,siz[i]=1;
	for (int i=1;i<n;i++) {
		int u=find(e[i].u),t=find(e[i].t);
		if (siz[u]>sum-X[u] || siz[t]>sum-X[t]) return printf("%d\n",ans),0;
		ans=e[i].w;
		V.push_back(make_pair(u,t));
		if (e[i].w!=e[i-1].w) {
			for (int j=0;j<(int)V.size();j++) {
				merge(V[j].first,V[j].second);
			}
			V.clear();
		}
	}
	printf("%d\n",e[n-1].w);
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int N=3007;
struct edge {
	int t,next,w;
}e[N*(N+4)*2];
int n,cnt,S,T;
int head[N<<2],res[N][N],x[N],dep[N<<2],cur[N<<2];
void add(int u,int t,int w) {
	e[++cnt].t=t;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;
}
void dfs(int u,int fa,int top) {
	for (int i=head[u];i;i=e[i].next) {
		int v=e[i].t;
		if (v==fa) continue;
		res[top][v]=res[v][top]=max(e[i].w,res[top][u]);
		dfs(v,u,top);
	}
}
queue<int>q;
bool bfs() {
    memset(dep,0,sizeof dep);
    q.push(S);
    dep[S]=1;
    while (!q.empty()) {
        int u=q.front();q.pop();
        for (int i=head[u];i;i=e[i].next) {
            int v=e[i].t;
            if (dep[v] || e[i].w==0) continue;
            dep[v]=dep[u]+1;
            q.push(v);
        }
    }
    if (!dep[T]) return 0;
    return 1;
}
int dfs1(int u,int wi) {
    if (u==T) return wi;
    for (int &i=cur[u];i;i=e[i].next) {
        int v=e[i].t;
        if (dep[v]!=dep[u]+1 || !e[i].w) continue;
        int k=dfs1(v,min(wi,e[i].w));
        if (k<=0) continue;
        e[i].w-=k;
        e[i^1].w+=k;
        return k;
    }
    return 0;
}
int dinic() {
    int ans=0;
    while (bfs()) {
    	for (int i=0;i<=T;++i) cur[i]=head[i];
        while (int k=dfs1(S,1e9)) ans+=k;
    }
    return ans;
}
bool check(int mid) {
	S=0,T=2*n+1;
	cnt=1;memset(head,0,sizeof head);
	for (int i=1;i<=n;i++) add(S,i,1),add(i,S,0);
	for (int i=1;i<=n;i++) add(i+n,T,x[i]),add(T,i+n,0);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++) {
			if (res[i][j]>=mid) add(i,j+n,1),add(j+n,i,0);
		}

	if (dinic()==n) return 1;
	return 0;
}
int main() {
	scanf("%d",&n);
	for (int i=1,u,v,w;i<n;i++) {
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);add(v,u,w);
	}
	for (int i=1;i<=n;i++) scanf("%d",&x[i]);
	for (int i=1;i<=n;i++) dfs(i,0,i);
	int l=1,r=10000;
	while (l<r) {
		int mid=(l+r+1)>>1;
		if (check(mid)) l=mid;
		else r=mid-1;
	}
	printf("%d\n",l);
}


#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define dd c=getchar()
inline int read() {int s=0,w=1;char c;while (dd,c>'9' || c<'0') if (c=='-') w=-1;while (c>='0' && c<='9') s=s*10+c-'0',dd;return s*w;}
#undef dd
const int N=3005;
struct edge {
	int u,t,w;
	bool operator <(edge a) const {
		return w<a.w;
	}
}e[N];
int n,sum,ans;
int X[N],siz[N],fa[N];
int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
vector<pair<int,int> > V;
void merge(int a,int b) {
	fa[b]=a;
	siz[a]+=siz[b];
	X[a]+=X[b];
}
int main() {
	n=read();
	if (n==1) return puts("0"),0;
	for (int i=1;i<n;i++) e[i].u=read(),e[i].t=read(),e[i].w=read();
	sort(e+1,e+n);
	for (int i=1;i<=n;i++) X[i]=read(),sum+=X[i];
	for (int i=1;i<=n;i++) fa[i]=i,siz[i]=1;
	for (int i=1;i<n;i++) {
		int u=find(e[i].u),t=find(e[i].t);
		if (siz[u]>sum-X[u] || siz[t]>sum-X[t]) return printf("%d\n",ans),0;
		V.push_back(make_pair(u,t));
		if (e[i].w!=e[i-1].w) {
			ans=e[i].w;
			for (int j=0;j<(int)V.size();j++) {
				merge(V[j].first,V[j].second);
			}
			V.clear();
		}
	}
	printf("%d\n",ans);
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int N=3007;
struct edge {
	int t,next,w;
}e[N*(N+2)*2];
struct node {
	int id,v;
	bool operator <(node a) const {
		return v<a.v;
	}
};
int n,cnt,S,T;
int head[N<<2],res[N][N],x[N],dep[N<<2],cur[N<<2];
vector<int> son[N];
void add(int u,int t,int w) {
	e[++cnt].t=t;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;
}
#define pb push_back
void dfs(int u,int fa) {
	for (int i=head[u];i;i=e[i].next) {
		int t=e[i].t;
		if (t==fa) continue;
		dfs(t,u);
		for (int j=0;j<(int)son[t].size();j++) {
			int tt=son[t][j];
			res[tt][u]=res[u][tt]=max(e[i].w,res[t][tt]);
		}
		for (int j=0;j<(int)son[t].size();j++) {
			for (int k=0;k<(int)son[u].size();k++) {
				int uu=son[u][k],tt=son[t][j];
				res[uu][tt]=res[tt][uu]=max(res[uu][u],res[tt][u]);
			}
		}
		for (int j=0;j<(int)son[t].size();j++) son[u].pb(son[t][j]);
	}
	son[u].pb(u);
}
queue<int>q;
bool bfs() {
    memset(dep,0,sizeof dep);
    q.push(S);
    dep[S]=1;
    while (!q.empty()) {
        int u=q.front();q.pop();
        for (int i=head[u];i;i=e[i].next) {
            int v=e[i].t;
            if (dep[v] || e[i].w==0) continue;
            dep[v]=dep[u]+1;
            q.push(v);
        }
    }
    if (!dep[T]) return 0;
    return 1;
}
int dfs1(int u,int wi) {
    if (u==T) return wi;
    for (int &i=cur[u];i;i=e[i].next) {
        int v=e[i].t;
        if (dep[v]!=dep[u]+1 || !e[i].w) continue;
        int k=dfs1(v,min(wi,e[i].w));
        if (k<=0) continue;
        e[i].w-=k;
        e[i^1].w+=k;
        return k;
    }
    return 0;
}
int dinic() {
    int ans=0;
    while (bfs()) {
    	for (int i=0;i<=T;++i) cur[i]=head[i];
        while (int k=dfs1(S,1e9)) ans+=k;
    }
    return ans;
}
bool check(int mid) {
	S=0,T=2*n+1;
	cnt=1;memset(head,0,sizeof head);
	for (int i=1;i<=n;i++) add(S,i,1),add(i,S,0);
	for (int i=1;i<=n;i++) add(i+n,T,x[i]),add(T,i+n,0);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++) {
			if (res[i][j]>=mid) add(i,j+n,1),add(j+n,i,0);
		}

	if (dinic()==n) return 1;
	return 0;
}
int main() {
	scanf("%d",&n);
	for (int i=1,u,v,w;i<n;i++) {
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);add(v,u,w);
	}
	for (int i=1;i<=n;i++) scanf("%d",&x[i]);
	dfs(1,0);
	int l=1,r=10000;
	while (l<r) {
		int mid=(l+r+1)>>1;
		if (check(mid)) l=mid;
		else r=mid-1;
	}
	printf("%d\n",l);
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int N=3007;
struct edge {
	int t,next,w;
}e[N<<4];
struct node {
	int id,v;
	bool operator <(node a) const {
		return v<a.v;
	}
};
int n,cnt,S,T;
int head[N<<2],res[N][N],x[N],dep[N<<2],cur[N<<2];
vector<int> son[N];
void add(int u,int t,int w) {
	e[++cnt].t=t;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;
}
#define pb push_back
void dfs(int u,int fa) {
	for (int i=head[u];i;i=e[i].next) {
		int t=e[i].t;
		if (t==fa) continue;
		dfs(t,u);
		for (int j=0;j<(int)son[t].size();j++) {
			int tt=son[t][j];
			res[tt][u]=res[u][tt]=max(e[i].w,res[t][tt]);
		}
		for (int j=0;j<(int)son[t].size();j++) {
			for (int k=0;k<(int)son[u].size();k++) {
				int uu=son[u][k],tt=son[t][j];
				res[uu][tt]=res[tt][uu]=max(res[uu][u],res[tt][u]);
			}
		}
		for (int j=0;j<(int)son[t].size();j++) son[u].pb(son[t][j]);
	}
	son[u].pb(u);
}
queue<int>q;
bool bfs() {
    memset(dep,0,sizeof dep);
    q.push(S);
    dep[S]=1;
    while (!q.empty()) {
        int u=q.front();q.pop();
        for (int i=head[u];i;i=e[i].next) {
            int v=e[i].t;
            if (dep[v] || e[i].w==0) continue;
            dep[v]=dep[u]+1;
            q.push(v);
        }
    }
    if (!dep[T]) return 0;
    return 1;
}
int dfs1(int u,int wi) {
    if (u==T) return wi;
    for (int &i=cur[u];i;i=e[i].next) {
        int v=e[i].t;
        if (dep[v]!=dep[u]+1 || !e[i].w) continue;
        int k=dfs1(v,min(wi,e[i].w));
        if (k<=0) continue;
        e[i].w-=k;
        e[i^1].w+=k;
        return k;
    }
    return 0;
}
int dinic() {
    int ans=0;
    while (bfs()) {
    	for (int i=0;i<=T;++i) cur[i]=head[i];
        while (int k=dfs1(S,1e9)) ans+=k;
    }
    return ans;
}
bool check(int mid) {
	S=0,T=2*n+1;
	cnt=1;memset(head,0,sizeof head);
	for (int i=1;i<=n;i++) add(S,i,1),add(i,S,0);
	for (int i=1;i<=n;i++) add(i+n,T,x[i]),add(T,i+n,0);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++) {
			if (res[i][j]>=mid) add(i,j+n,1),add(j+n,i,0);
		}

	if (dinic()==n) return 1;
	return 0;
}
int main() {
	scanf("%d",&n);
	for (int i=1,u,v,w;i<n;i++) {
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);add(v,u,w);
	}
	for (int i=1;i<=n;i++) scanf("%d",&x[i]);
	dfs(1,0);
	int l=1,r=10000;
	while (l<r) {
		int mid=(l+r+1)>>1;
		if (check(mid)) l=mid;
		else r=mid-1;
	}
	printf("%d\n",l);
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int N=3007;
struct edge {
	int t,next,w;
}e[N*N*3];
int n,cnt,S,T;
int head[N<<2],res[N][N],x[N],dep[N<<2],cur[N<<2];
void add(int u,int t,int w) {
	e[++cnt].t=t;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;
}
void dfs(int u,int fa,int top) {
	for (int i=head[u];i;i=e[i].next) {
		int v=e[i].t;
		if (v==fa) continue;
		res[top][v]=res[v][top]=max(e[i].w,res[top][u]);
		dfs(v,u,top);
	}
}
queue<int>q;
bool bfs() {
    memset(dep,0,sizeof dep);
    q.push(S);
    dep[S]=1;
    while (!q.empty()) {
        int u=q.front();q.pop();
        for (int i=head[u];i;i=e[i].next) {
            int v=e[i].t;
            if (dep[v] || e[i].w==0) continue;
            dep[v]=dep[u]+1;
            q.push(v);
        }
    }
    if (!dep[T]) return 0;
    return 1;
}
int dfs1(int u,int wi) {
    if (u==T) return wi;
    for (int &i=cur[u];i;i=e[i].next) {
        int v=e[i].t;
        if (dep[v]!=dep[u]+1 || !e[i].w) continue;
        int k=dfs1(v,min(wi,e[i].w));
        if (k<=0) continue;
        e[i].w-=k;
        e[i^1].w+=k;
        return k;
    }
    return 0;
}
int dinic() {
    int ans=0;
    while (bfs()) {
    	for (int i=0;i<=T;++i) cur[i]=head[i];
        while (int k=dfs1(S,1e9)) ans+=k;
    }
    return ans;
}
bool check(int mid) {
	S=0,T=2*n+1;
	cnt=1;memset(head,0,sizeof head);
	for (int i=1;i<=n;i++) add(S,i,1),add(i,S,0);
	for (int i=1;i<=n;i++) add(i+n,T,x[i]),add(T,i+n,0);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++) {
			if (res[i][j]>=mid) add(i,j+n,1),add(j+n,i,0);
		}

	if (dinic()==n) return 1;
	return 0;
}
int main() {
	scanf("%d",&n);
	for (int i=1,u,v,w;i<n;i++) {
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);add(v,u,w);
	}
	for (int i=1;i<=n;i++) scanf("%d",&x[i]);
	for (int i=1;i<=n;i++) dfs(i,0,i);
	int l=1,r=10000;
	while (l<r) {
		int mid=(l+r+1)>>1;
		if (check(mid)) l=mid;
		else r=mid-1;
	}
	printf("%d\n",l);
}