思路

  令黑点点权为 -1 , 白点点权为 1,求最大子树点权和。

  设 f[i] 为包含 i 点的最大子树点权值,如果当前点的最大点权和  比  当前点父亲的最大点权和小, 则更新当前点。

  比较蠢的做法是,分两种情况讨论下,当前点的点权和 大于 或 小于 0 的情况处理是不同的。

  如果当前点子树权值 >= 0,且父亲的子树权值更大,应该把父亲点的子树归并到当前点的子树中。

  如果当前点子树权值  <  0,且父亲的子树中白的比黑的多,就把父亲点的子树归并到当前点子树上。

 

CODE

 

#include  < bits/stdc++.h >
#define  dbg ( x ) cout  << #x  <<  " = "  << x  << endl
#define  eps  1e - 8
#define  pi  acos ( - 1.0 )

using  namespace  std ;
typedef  long  long LL ;

const  int inf  =  0x3f3f3f3f ;

template < class  T > inline  void  read ( T  & res )
{
     char c ;T flag = 1 ;
     while ((c = getchar ()) < ' 0 ' ||c > ' 9 ' ) if (c == ' - ' )flag =- 1 ;res =c - ' 0 ' ;
     while ((c = getchar ()) >= ' 0 ' &&c <= ' 9 ' )res =res * 10 +c - ' 0 ' ;res *=flag ;
}

namespace  _buff  {
     const  size_t BUFF  =  1  <<  19 ;
     char  ibuf [BUFF ],  *ib  = ibuf ,  *ie  = ibuf ;
     char  getc ()  {
         if  (ib  == ie )  {
            ib  = ibuf ;
            ie  = ibuf  +  fread (ibuf ,  1 , BUFF , stdin );
         }
         return ib  == ie  ?  - 1  :  *ib ++ ;
     }
}

int  qread ()  {
     using  namespace  _buff ;
     int ret  =  0 ;
     bool pos  =  true ;
     char c  =  getc ();
     for  (;  (<  ' 0 '  || c  >  ' 9 ' )  && c  !=  ' - ' ; c  =  getc ())  {
         assert ( ~c );
     }
     if  (==  ' - ' )  {
        pos  =  false ;
        c  =  getc ();
     }
     for  (; c  >=  ' 0 '  && c  <=  ' 9 ' ; c  =  getc ())  {
        ret  =  (ret  <<  3 )  +  (ret  <<  1 )  +  (^  48 );
     }
     return pos  ? ret  :  -ret ;
}

const  int maxn  =  2e5  +  7 ;

int a [maxn ];
int n ;
int head [maxn  <<  1 ], edge [maxn  <<  1 ], nxt [maxn  <<  1 ], cnt ;
int f [maxn ];
bool vis [maxn ];
int ans [maxn ];

void  BuildGraph ( int  u ,  int  v )  {
    cnt ++ ;
    edge [cnt ]  = v ;
    nxt [cnt ]  = head [u ];
    head [u ]  = cnt ;
}

void  dfs ( int  u ,  int  fa )  {
     if (a [u ]  ==  1 )  {
         f [u ]  =  1 ;
     }
     else  {
         f [u ]  =  - 1 ;
     }
    //printf("f[%d]:%d\n",u, f[u]);
     for  (  int i  = head [u ]; i ; i  = nxt [i ]  )  {
         int v  =  edge [i ];
         if (== fa )
             continue ;
         else  {
             dfs (v , u );
             if ( f [v ]  >  0 )  {
                 f [u ]  +=  f [v ];
                //printf("f[%d]:%d\n",u, f[u]);
             }
         } 
     }
}

void  dp ( int  u ,  int  fa )  {
     if (f [u ]  >=  0 )  {
         int temp  =  f [fa ]  -  f [u ];
         if (temp  >=  0 )  {
             f [u ]  += temp ;
            //printf("f[%d]:%d\n",u, f[u]);
         }
     }
     else  {
        //printf("fa: f[%d]:%d\n",fa, f[fa]);
         if ( f [fa ]  >=  0 )  {
             f [u ]  +=  f [fa ];
            //printf("f[%d]:%d\n",u, f[u]);
         }
     }
     for  (  int i  = head [u ]; i ; i  = nxt [i ]  )  {
         int v  =  edge [i ];
        //dbg(v);
         if (== fa )
             continue ;
         else  {
             dp (v , u );
         }
     }
}

int  main ()
{
     read (n );
     for  (  int i  =  1 ; i  <= n ;  ++)  {
         read ( a [i ]);
     }
     for  (  int i  =  1 ; i  < n ;  ++)  {
         int u , v ;
         read (u );
         read (v );
         BuildGraph (u , v );
         BuildGraph (v , u );
     }
     dfs ( 1 ,  1 );
     dp ( 1 ,  1 );
     for  (  int i  =  1 ; i  <= n ;  ++)  {
         printf ( "%d   " , f [i ]);
     }
     return  0 ;
}