zoukankan      html  css  js  c++  java
  • hdu

    题意:一棵有n个结点的树,编号从0(根结点)开始,Alice和Bob一起从0走到叶子结点,Alice走最短路,Bob走最长路,Bob先选择下一个结点,然后两个一起走到那个结点,接着Alice选择下一个结点……,总长度要在[L, R]内,问这种走法的最长路的长度(1 <= n <= 500000, 0 <= L, R <= 1000000000, 1 <= 相邻结点间距离 <= 1000)。

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3660

    ——>>怒刷树状dp。。。

    设da[i]为Alice从结点i出发走到叶子的最短距离,则

    状态转移方程为:da[x] = min(da[x], db[v[e]] + w[e]);

    设db[i]为Bob从结点i出发走到叶子的最长距离,则

    状态转移方程为:db[x] = max(db[x], da[v[e]] + w[e]);

    加上IO优化,以C++提交~

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cctype>
    
    using namespace std;
    
    const int maxn = 500000 + 10;
    const int INF = 0x3f3f3f3f;
    int n, L, R, head[maxn], nxt[maxn], u[maxn], v[maxn], w[maxn], ecnt, da[maxn], db[maxn];
    
    void init(){
        ecnt = 0;
        memset(head, -1, sizeof(head));
    }
    
    void addEdge(int uu, int vv, int ww){
        u[ecnt] = uu;
        v[ecnt] = vv;
        w[ecnt] = ww;
        nxt[ecnt] = head[uu];
        head[uu] = ecnt;
        ecnt++;
    }
    
    int nextInt(){
        char c = getchar();
        while(!isdigit(c)) c = getchar();
        int ret = 0;
        while(isdigit(c)){
            ret = ret * 10 + c - '0';
            c = getchar();
        }
        return ret;
    }
    
    void read(){
        int uu, vv, ww, i;
        for(i = 0; i < n-1; i++){
            uu = nextInt();
            vv = nextInt();
            ww = nextInt();
            addEdge(uu, vv, ww);
        }
    }
    
    void dp(int x, int cur){
        da[x] = head[x] == -1 ? 0 : INF;
        db[x] = 0;
        for(int e = head[x]; e != -1; e = nxt[e]){
            int len = cur + w[e];
            if(len <= R) dp(v[e], len);
            if(len + db[v[e]] >= L && len + db[v[e]] <= R) da[x] = min(da[x], db[v[e]] + w[e]);
            if(len + da[v[e]] >= L && len + da[v[e]] <= R) db[x] = max(db[x], da[v[e]] + w[e]);
        }
    }
    
    void solve(){
        dp(0, 0);
        if(db[0]) printf("%d
    ", db[0]);
        else puts("Oh, my god!");
    }
    
    int main()
    {
        while(scanf("%d%d%d", &n, &L, &R) == 3){
            init();
            read();
            solve();
        }
        return 0;
    }
    
    


  • 相关阅读:
    <<剪绳子>>题解
    P5743 小猴吃桃 题解
    注意C++中的int与long long 的乘法
    数组初始化方法总结
    一维差分和二维差分
    一维前缀和与二维前缀和
    例2-6 字母转换
    例1-11 评测机队列
    golang ---查找字串实例 IP address
    mongodb ---加减等操作
  • 原文地址:https://www.cnblogs.com/pangblog/p/3271005.html
Copyright © 2011-2022 走看看