計蒜之道2016第六場

題目鏈接:微軟員工的福利(中等)

題意是………………題面描述的那樣…..中文題.
我只想到了中等的解法,就是對於一個點直接枚舉他兒子和他自己的兩個最值,然後樹型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 long
const 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 , 1
struct 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 ;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章