uva-1484(hdu-3660) Alice and Bob's Trip 听说是树形dp

下午组队赛遇到的题,是在hdu上判,一直在超时,各种优化之后还是超时,最后无奈从别人博客上贴代码交,竟然还是超时,但是后来我在uva 上交,我的代码只跑了300多ms,呵呵……,然后我看那个题在hdu上最后一次ac发生在今年1月6号,我也发现还有好多和我有着同样遭遇的,果断放弃,所有下面的代码c++和java都只能在uva 上通过。(之所以要写两遍,是我寄希望于java能通过hdu诡异的测试,但是无果,而且在uva上跑的时间也比较长)。吐槽完还是说题吧。

题意:给一棵n节点的树,每条边都有权值,从根节点走到叶节点,alice希望走的路尽可能短,bob希望走的尽可能长,但是最后走过的路要在l和r之间,bob先走,没人都会做最优选择,问满足条件的最大值。

听说这是一个树形dp,但是我看方法跟我差不多,但是我没感觉是dp呢,可能还是太水。我觉得就是一个dfs,先处理出子每一个子树的状态,bob走时,节点选择子节点到叶节点最大的值,alice走时选择最小,f值为1或-1,用在比较大小的时候,1表示bob走,-1表示alice走,最后对根节点dfs返回的就是最终结果。

c++代码:

#include <string.h>
#include <stdio.h>
struct edge {
    int v, l, nxt;
}e[500050];
struct node {
    int mn, e;
}id[500050];
int n, l, r, no, tmp;
int dfs(int u, int f) {
//    if(cost > r) return -1;
    if(id[u].e == -1) {
        if(id[u].mn >= l && id[u].mn <= r) {
            return id[u].mn;
        }
        return -1;
    }
    int t = -1, i;
    for(i = id[u].e; i != -1; i = e[i].nxt) {
        id[e[i].v].mn = id[u].mn + e[i].l;
        tmp = dfs(e[i].v, f * -1);
        if(tmp != -1) {
            if(t == -1 || (t - tmp) * f < 0)
                t = tmp;
        }
    }
    return t;
}
int main() {
    int i, j, a, b, c, t;
    while(~scanf("%d%d%d", &n, &l, &r)) {
        memset(id, -1, sizeof(id));
        no = 0;
        id[0].mn = 0;
        for(i = 1; i < n; i++) {
            scanf("%d%d%d", &a, &b, &c);
            e[no].v = b;
            e[no].l = c;
            e[no].nxt = id[a].e;
            id[a].e = no++;
        }
        t = dfs(0, 1);
        if(t == -1)
            printf("Oh, my god!\n");
        else printf("%d\n", t);
    }
    return 0;
}
java代码:

import java.util.Scanner;

class edge{
	int v, l, nxt;
}
public class Main {
	static int v[];
	static edge e[];
	static int n, l, r, no;
	static int dfs(int u, int cost, int f) {
		if(cost > r) return -1;
		if(v[u] == -1) {
			if(cost >= l && cost <= r) return cost;
			return -1;
		}
		int t = -1;
		for(int i = v[u]; i != -1; i = e[i].nxt) {
	        int tmp = dfs(e[i].v, cost + e[i].l, f * -1);
	        if(tmp != -1) {
	            if(t == -1 || (t - tmp) * f < 0)
	                t = tmp;
	        }
	    }
	    return t;
	}
	public static void main(String[] args) {
		int i, a, b, c;
		v = new int[500050];
		e = new edge[500050];
		if(e == null) {
			System.out.println("WA");
		}
		Scanner in = new Scanner(System.in);
		while(in.hasNext()) {
			n = in.nextInt();
			l = in.nextInt();
			r = in.nextInt();
			for(i = 0; i < n; i++)
				v[i] = -1;
			no = 0;
			for(i = 1; i < n; i++) {
				a = in.nextInt();
				b = in.nextInt();
				c = in.nextInt();
//				System.out.println(a + " " + b + " " + c);
				e[no] = new edge();
				e[no].v = b;
				e[no].l = c;
				e[no].nxt = v[a];
//				System.out.println(a + " " + b + " " + c);
				v[a] = no++;
			}
			int t = dfs(0, 0, 1);
			if(t == -1) 
				System.out.println("Oh, my god!");
			else System.out.println(t);
		}
		in.close();
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值