计蒜之道2016第六场

来源:互联网 发布:openwrt破解网络尖兵 编辑:程序博客网 时间:2024/06/10 04:20

题目链接:微软员工的福利(中等)

题意是………………题面描述的那样…..中文题.
我只想到了中等的解法,就是对于一个点直接枚举他儿子和他自己的两个最值,然后树型dp,复杂度是O(n³),思路比较清晰但是写起代码来比较复杂,因为在枚举最大值最小值的时候要考虑到这个最值是不是该点他本身.

#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<set>#include<map>#include<time.h>#include<cstdio>#include<vector>#include<list>#include<stack>#include<queue>#include<iostream>#include<stdlib.h>using namespace std;#define  LONG long longconst LONG   INF = 0x3f3f3f3f;const LONG  MOD = 1e9+ 7;const double PI = acos(-1.0);#define clrI(x) memset(x,-1,sizeof(x))#define clr0(x) memset(x,0,sizeof x)#define clr1(x) memset(x,INF,sizeof x)#define clr2(x) memset(x,-INF,sizeof x)#define EPS 1e-10#define lson  l , mid , rt<< 1#define rson  mid + 1 ,r , (rt<<1)+1#define root 1, m , 1struct Edge{    LONG to ,next , u ;}edge[500] ;LONG tot = 0 ;LONG head[500 ] ;LONG R[400 ] ;LONG P[400 ] ;LONG dp[400][2] ;LONG son[400] ;void Init(){    tot =0 ;    clrI(head) ;    clr0(dp)  ;}void Add_edge(LONG u , LONG v ){    edge[++tot].to = v ;    edge[tot].next = head[u] ;    edge[tot].u = u ;    head[u] = tot ;}void dfs(LONG pre , LONG u ){    LONG p = 0;    for(LONG i = head[u] ; ~i ; i =edge[i].next)    {        LONG v = edge[i].to ;        if(v == pre) continue;        dfs(u , v) ;    }    son[++p] = u ;    for(LONG i = head[u] ; ~i ; i =edge[i].next)    {        LONG v = edge[i].to ;        if(v == pre) continue ;        son[++p] = v ;    }    ;    if(p == 1)    {        dp[u][0] = P[u] ;        dp[u][1] = R[u] ;        return ;    }    if(p == 2)    {        LONG t = son[2] ;        LONG r1 = abs(R[t] - P[u]) ;        LONG r2 = abs(P[t] - P[u]) ;        dp[u][0] = max( -(r1 + 999) / 1000 * 666 * u  + P[u] + dp[t][1] , -(r2 + 999) / 1000 * 666 * u  + P[u] + dp[t][0] ) ;        r1 = abs(R[t] - R[u]) ;        r2 = abs(P[t] - R[u]) ;        dp[u][1] = max(-(r1 + 999)/1000 * 666 * u + R[u] + dp[t][1] , -(r2+ 999) / 1000 * 666 * u + R[u] + dp[t][0]) ;        return ;    }    dp[u][0] = -1e15  ;    dp[u][1] = -1e15 ;    for(LONG _ii = 0 ; _ii <= 1 ; _ii ++ ){        LONG res = -1e15 ;        LONG tag  ;        if(_ii == 0) tag = P[u] ;        else tag = R[u] ;    for(LONG i = 2 ; i <= p ; ++ i)    {        for(LONG j = 2 ; j <= p ; ++j)        {            if(i == j) continue ;            LONG maxn , minx ;            //            for(LONG _tt = 1 ;  _tt <= 4 ;++ _tt){            LONG x = son[i] , y = son[j] ;            if(_tt == 1)            maxn = P[x] ,minx = P[y] ;            else if(_tt == 2)            maxn = P[x] , minx = R[y] ;            else if(_tt == 3)            maxn = R[x] , minx = P[y] ;            else            maxn = R[x] ,minx = R[y] ;            if(tag > maxn  ) maxn = tag , x = 0 ;            if(tag < minx ) minx = tag ,y = 0 ;            if(maxn < minx ) continue ;            LONG judge = 1;            for(LONG k = 2 ; k <= p ; ++k)            {                LONG t = son[k] ;                if(R[t] >= minx && R[t] <= maxn ||P[t] >=minx &&P[t] <=maxn   )                {}                else                {                    judge = 0 ;break ;                }            }            if(judge )            {                LONG temp ;                if(_tt == 1)                temp = dp[x][0] + dp[y][0] ;                else if(_tt == 2)                temp = dp[x][0] +dp[y][1] ;                else if(_tt == 3)                temp = dp[x][1] +dp[y][0] ;                else                temp = dp[x][1] + dp[y][1] ;                LONG tmp =  temp  - (maxn - minx + 999 ) / 1000 * 666 * u;                for(LONG k = 2 ; k <= p ; ++k)                {                    LONG t = son[k] ;                    if(t == x || t == y) continue ;                    if(R[t]  <=maxn && P[t] <= maxn && R[t] >= minx && P[t] >= minx )                        tmp += max( dp[t][0] , dp[t][1]) ;                    else if( P[t ] <= maxn && P[t] >= minx )                        tmp += dp[t][0] ;                    else tmp += dp[t][1] ;                }                tmp += tag ;                if(_ii == 0)                dp[u][0] = max(dp[u][0] , tmp ) ;                else dp[u][1] = max(dp[u][1] , tmp) ;            }            }        }    }    }}int main(){    Init() ;    LONG n ;    cin >>n ;    LONG u , v;    for(LONG i =1; i<= n ;++ i)        scanf("%lld%lld" ,&R[i] , &P[i]) ;    for(LONG i = 1 ;i < n ; ++i)    {        scanf("%lld%lld",&u,&v ) ;        Add_edge(u , v ) ;        Add_edge(v , u ) ;    }    dfs(-1 , 1) ;    printf("%lld\n",max(dp[1][0],dp[1][1]));    return 0 ;}
阅读全文
1 0