void main(){
  import std.stdio, std.string, std.conv, std.algorithm;
  import std.typecons;

  int n; rd(n);
  auto g=new int[][](n, 0);
  alias Edge=Tuple!(int, "a", int, "b");
  auto edges=new Edge[](n-1);
  foreach(i; 0..(n-1)){
    int a, b; rd(a, b);
    a--; b--;
    g[a]~=b; g[b]~=a;
    edges[i]=Edge(a, b);
  }
  auto s=readln.split.to!(long[]);

  auto sz=new long[](n), par=new int[](n);
  void dfs(int i, int p=-1){
    sz[i]=1;
    par[i]=p;
    foreach(j; g[i])if(j!=p){
      dfs(j, i); sz[i]+=sz[j];
    }
  }

  dfs(0);
  auto c=new long[](n-1);
  foreach(i, e; edges){
    auto a=e.a, b=e.b;
    if(par[a]==b) swap(a, b);  // a
    auto na=n-sz[b], nb=sz[b]; // |
    if(na==nb) continue;       // b
    c[i]=(s[a]-s[b])/(nb-na);
  }

  auto idx=-1;
  foreach(i; 0..(n-1)){
    if(c[i]==0){idx=i; break;}
  }
  if(idx==-1){
    writefln("%(%s\n%)", c); return;
  }

  alias T=Tuple!(int, "to", long, "c");
  auto g2=new T[][](n, 0);
  foreach(i, e; edges){
    g2[e.a]~=T(e.b, c[i]);
    g2[e.b]~=T(e.a, c[i]);
  }

  long dfs2(int i, long size, int p=-1){
    long ret=0;
    foreach(e; g2[i])if(e.c>0){
      if(e.to==p){
        ret+=e.c*(size-1);
      }else{
        ret+=dfs2(e.to, size-(g2[i].length-1)+1, i);
      }
    }
    return ret;
  }
  
  auto va=edges[idx].a, vb=edges[idx].b;
  if(par[va]==vb) swap(va, vb);
  auto suba=dfs2(va, n-sz[vb]), subb=dfs2(vb, sz[vb]);
  c[idx]=(s[va]-(suba+subb))/sz[vb];

  writefln("%(%s\n%)", c);
}


void rd(T...)(ref T x){
  import std.stdio, std.string, std.conv;
  auto l=readln.split;
  assert(l.length==x.length);
  foreach(i, ref e; x){
    e=l[i].to!(typeof(e));
  }
}