HDU_3660

    首先如果下一步到达某个节点后,无论怎么走都不能使路径和在L、R之内的话,那么是肯定不能走这一步的。至于如何找到这些不能走的节点,可以从叶子节点开始,如果这条路径和不在L、R之内,那么就将这个叶子标记为-1,表示不能来这个节点,对于其他的节点,如果它的所有孩子都被标记成了-1,那么它本身也应被标记-1。

    这样我们只要沿不是-1的点走就可以了,接下来如何计算最大的可能值呢?对于Bob来讲,显然应该在所有的路中挑“最终可能得到的值最大”的那条路去走,而Alice就应该选择“最终可能得到的值最小”的那条路去走,那怎么才能知道最终可能的值是多少呢?只要从叶子节点开始向上依次计算就可以了。

    此外,这个题目不用读入优化的话比较容易超时。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXD 500010
#define INF 0x3f3f3f3f
int N, L, R, first[MAXD], e, next[MAXD], v[MAXD], w[MAXD], col[MAXD], dp[MAXD], dis[MAXD];
int q[MAXD];
void add(int x, int y, int z)
{
    v[e] = y, w[e] = z;
    next[e] = first[x], first[x] = e ++;    
}
void scan(int &a)
{
    char c;
    while ((c = getchar()) == ' ' || c == '\n');
    a = c - 48;
    while ((c = getchar()) >= '0' && c <= '9')
        a = (a << 3) + (a << 1) + c - 48;
}
void init()
{
    int i, x, y, z;
    memset(first, -1, sizeof(first[0]) * N), e = 0;
    for(i = 1; i < N; i ++)
        scan(x), scan(y), scan(z), add(x, y, z);
}
void solve()
{
    int i, j, x, rear = 0, flag;
    col[0] = 1, dis[0] = 0, q[rear ++] = 0;
    for(i = 0; i < rear; i ++)
    {
        x = q[i];
        for(j = first[x]; j != -1; j = next[j])
            col[v[j]] = col[x] ^ 1, dis[v[j]] = dis[x] + w[j], q[rear ++] = v[j];
    }
    for(i = rear - 1; i >= 0; i --)
    {
        x = q[i];
        flag = 0;
        if(col[x] == 0)
        {
            dp[x] = INF;
            for(j = first[x]; j != -1; j = next[j])
            {
                flag = 1;
                if(dp[v[j]] != -1) dp[x] = std::min(dp[x], dp[v[j]] + w[j]);
            }
        }
        else
        {
            dp[x] = -INF;
            for(j = first[x]; j != -1; j = next[j])
            {
                flag = 1;
                if(dp[v[j]] != -1) dp[x] = std::max(dp[x], dp[v[j]] + w[j]);
            }
        }
        if(flag == 0) dp[x] = dis[x] >= L && dis[x] <= R ? 0 : -1;
        else if(dp[x] == INF || dp[x] == -INF) dp[x] = -1;
    }
    if(dp[0] >= L && dp[0] <= R) printf("%d\n", dp[0]);
    else printf("Oh, my god!\n");
}
int main()
{
    while(scanf("%d%d%d", &N, &L, &R) == 3)
    {
        init();
        solve();    
    }
    return 0;    
}
posted on 2012-08-30 17:58  Staginner  阅读(447)  评论(0编辑  收藏  举报