• HDU 3660 Alice and Bob's Trip


    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;    
    }
  • 相关阅读:
    (原)在ubuntu 中安装 swi prolog 和 简单的使用
    (转) 新手入门:C/C++中的结构体
    (转) eclipse debug (调试) 学习心得
    flutter: 根视图、根元素与根渲染
    eggjs的参数校验模块egg-validate的使用和进一步定制化升级
    Vue源码中用到的工具函数
    21 项优化 React App 性能的技术
    react-redux 的使用
    编写 Vue.js 组件前需要知道的 10 件事
    Flutter实现抽屉动画效果
  • 原文地址:https://www.cnblogs.com/staginner/p/2664198.html
Copyright © 2020-2023  润新知