UVA1484 Alice and Bob's Trip (hdu3660)

 一、前言

  最开始卡这题是某大佬给出的树DP专题中的一个,据说类似于对抗搜索(这是啥?)的一题

  但是在经历了若干艰难困苦之后发现这题在HDU上A不了——(先卡vector的时间,后卡输入的时间,上了输入挂还是玄学超时)。于是遵从百度到的大佬指点,上UVA上面交了一发,发现500毫秒过得。。。感觉心好累。。。。

二、题意

  A,B两人计划在一棵树上旅行,A想尽量短,B想尽量长,但是有个区间规定了这个时间长短:L和R。考虑到是B开始出发,于是求能够在L-R区间内得到的最远的距离。如果得不到就输出“Oh, my god!”

  思路大概是,设DP【i】为第i号节点的最优解——(不论是对A还是B来说的最优解)。能这么干是因为,树的形状、起始节点一旦给定就会使得每个节点由射来选择成为一个固定选项。因而可以直接这么设定。于是,剩下的比较简单——A在区间内选最小,B在区间内选最大。

#include<stdio.h>
#include<string.h>
using namespace std;
#define ll int
#define pp pair<int,ll> 
#define vecp vector<pp>

const long long MAXN=502333;

//vecp G[MAXN];

inline void read_int(int &ret)
{
    ret=0;
    char c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c<='9'&&c>='0')ret=ret*10+c-'0',c=getchar();
}

class node
{
    public:
        int next;
        int to;
        ll cost;
        void make(int next,int a,ll b)
        {
            this->next=next;
            to=a;
            cost=b;
        }
    
};node G[MAXN*3];
int number[MAXN];
int size;int cnt[MAXN];
void add(int a,int b,ll c)
{
//    number[a]=size;
    cnt[a]++;
    G[size].make(number[a],b,c);
    number[a]=size++;
}


ll dp[MAXN];
ll n,l,r;

inline bool check(ll tmp)
{
    return tmp>=l&&tmp<=r;
}

void checkMin(ll &a,ll b)
{
    a= a==-1||a>b ? b:a;
}
void checkMax(ll &a,ll b)
{
    a= a==-1||a<b ? b:a;
}

void dfs(int now,int last,ll maxx,bool isBob)
{
//    int len=G[now].size();
    
    dp[now]=-1;
    for(int i=number[now];i!=-1;i=G[i].next)
//    for(int i=0;i<len;++i)
    {
        int tar=G[i].to;
//        int tar=G[now][i].first;
        if(tar==last)continue;
//        ll cost=G[now][i].second;
        ll cost=G[i].cost;
        dfs(tar,now,maxx+cost,!isBob);
        if(dp[tar]==-1)continue;
        ll summ=maxx+cost+dp[tar];
        if(!check(summ))continue;
        if(isBob)checkMax(dp[now],dp[tar]+cost);
        else checkMin(dp[now],dp[tar]+cost);        
    }
    if(cnt[now]==1&&dp[now]==-1)dp[now]=0;
//    if(len==1&&dp[now]==-1)dp[now]=0;
}


void init()
{
    memset(number,-1,4*(n+1));
    memset(cnt,0,4*(n+1));
    size=0;
    for(int i=1;i<n;++i)
    {
        ll a,b,c;
        read_int(a);
        read_int(b);
        read_int(c);
//        scanf("%d%d%d",&a,&b,&c);
//        cin>>a>>b>>c;
//        G[a].push_back(make_pair(b,c));
//        G[b].push_back(make_pair(a,c));

        add(a,b,c);
        add(b,a,c);
    }
    dfs(0,-1,0,1);
    if(dp[0]!=-1)printf("%d\n",dp[0]);
//    cout<<dp[0]<<"\n";
    else puts("Oh, my god!");
}

int main()
{
//    cin.sync_with_stdio(false);
    while(scanf("%d%d%d",&n,&l,&r)!=EOF&&n&&l&&r)init();
    
    return 0;
}

 

posted @ 2017-11-26 18:43  六花的邪王真眼  阅读(149)  评论(0编辑  收藏  举报