训练指南UVALive5088解题报告

Alice and Bob’s Trip
I - Alice and Bob’s Trip
Time Limit:6000MS Memory Limit:0KB 64bit IO Format:%lld & %llu
Submit

Status

Practice

UVALive 5088
Appoint description:
Description
Download as PDF
Alice and Bob are going on a trip. Alice is a lazy girl who wants to minimize the total travelling distance, while Bob as an active boy wants to maximize it. At the same time, they cannot let the value to be less than a given integer L since that will make them miss too much pleasure, and they cannot let the value to be greater than a given integer R since they don’t want to get too exhausted.
The city they are visiting has n spots and the spots are connected by directed edges. The spots are connected in such a way that they form a tree and the root will always be at spot 0. They take turns to select which edge to go. Both of them choose optimally. Bob will go first.
Input
There are multiple test cases. For every test case, the first line has three integers, n, L and R(1 n 500000, 0 L, R 1000000000). The next n - 1 lines each has three integers a, b and c, indicating that there is an edge going from spot a to spot b with length c(1 c 1000). The spots are labeled from 0 to n - 1.
There is a blank line after each test case.
Proceed to the end of file.
Output
If the total distance is not within the range [L, R], print “Oh, my god!” on a single line. Otherwise, print the most value Bob can get.
Sample Input
3 2 4
0 1 1
0 2 5

7 2 8
0 1 1
0 2 1
1 3 1
1 4 10
2 5 1
2 6 5

7 4 8
0 1 1
0 2 1
1 3 1
1 4 2
2 5 1
2 6 5

4 2 6
0 1 1
1 2 1
1 3 5
Sample Output
Oh, my god!
2
6
2
题意:
给你一个n个节点的树,一个l, r表示闭区间
根节点为0,然后接下来n-1行表示u, v, val,连边
,然后alice和bob 从0点出发。bob先选一条边走,然后alice再选,他们轮换着来,bob想让两个人走的尽量远,alice想让两个人走的尽量近,但是他们走的总路程,必须在l到r闭区间,为了尽量满足bob的要求,问你最长的距离是多少,或者根本走不到满足l,r的区间输出Oh, my god!

解析。树形dp显然的。
两位状态表示以i为根的树,走当前l,r区间能走的最大值(bob)最小值(alice)
由博弈的一些知识,状态转移也是显然的
我用0表示bob选,1表示alice选
dp[u][0] = max(dp[v][1] + cost[i]) 选的前提是满足当前L,R区间
dp[v][1] = min(dp[u][0] + cost[i]) 选的前提同上

一个小问题,我一开始把dp[u][1](当它不做叶子节点的时候)在一开始就初始化为inf,一直wa,
然后后来改在比较的时候判断它是不是0,是0就表达为inf就ac了。莫名其妙的。
代码如下

//
//  Created by Matrix on 2015-10-07
//  Copyright (c) 2015 Matrix. All rights reserved.
//
//
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;


inline int read() {
    char c = getchar();
    int f = 1;
    while(!isdigit(c)) {
    if(c == '-') f = -1;
    c = getchar();
    }
    int x = 0;
    while(isdigit(c)) {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x * f;
}
int n, cnt;

int nxt[maxn], pnt[maxn], head[maxn], cost[maxn];
void add_edge(int u, int v, int val) {
    pnt[cnt] = v;
    cost[cnt] = val;
    nxt[cnt] = head[u];
    head[u] = cnt++;
}
int dp[maxn][2];

void dfs(int u, int fa, int op, int l, int r) {
    dp[u][op] = 0;
    dp[u][!op] = 0;
    for(int i = head[u]; ~i; i = nxt[i]) {
        int v = pnt[i];
        if(v == fa) continue;
        dfs(v, u, !op, l - cost[i], r - cost[i]);
        int tmp = dp[v][!op] + cost[i];
        if(tmp < l || tmp > r) continue;
        printf("tmp = %d\n", tmp);
        printf("l = %d r = %d\n", l, r);

        if(!op) {
            dp[u][op] = max(tmp, dp[u][op]);
        }
        else {
            dp[u][op] = min(tmp, !dp[u][op] ? inf : dp[u][op]);
        }
//      printf("dp[%d][%d] = %d\n", u, op, dp[u][op]);
    }

}
int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    int l, r;
    while(scanf("%d%d%d", &n, &l, &r) != EOF) {
        memset(head, -1, sizeof head);
        cnt = 0;
        for(int i = 1; i < n; i++) {
            int u, v, val;
            scanf("%d%d%d", &u, &v, &val);
            add_edge(u, v, val);
            add_edge(v, u, val);
        }
        dfs(0, 0, 0, l, r);
        if(dp[0][0] <= r && dp[0][0] >= l) printf("%d\n", dp[0][0]);
        else puts("Oh, my god!");
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值