您的位置:首页 > 其它

uva1484

2015-06-08 09:16 141 查看

bob和alice

题目描述:

一棵树,bob想要尽量往远的走,alice想要尽量往近的走,并且他们约定走的距离必须是[l,r]内.问bob先走,alice后走,问最终会走到哪里

题解:

画出树,发现是递归的不用看具体的子树张什么样的,所以用树形dp.就是奇偶从子树中挑最大的和最小的.关键是:因为有[l,r]的限制,所以要一直有一个road跟踪值,来确保取得的最值是有效[l,r]中的最值,而不是当前u问根开始从0计算长度的最值,防止丢掉有效数.

重点:

不用管子树的具体,只用保留一些结果.用树形dp.关键是想清楚[l,r]对全局的限制.

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)

typedef long long ll;

using namespace std;

const int maxn = 500000+10;
const int INF = 1e9 +10;
int l, r, n, dp[maxn];
struct info
{
int to, len, next;
};
info edge[maxn*2];
int head[maxn];
int tot;

void add_edge(int a, int b, int l)//本题没用vector
{
edge[tot].len = l;
edge[tot].to = b;
edge[tot].next = head[a];
head[a] = tot;
tot++;
}
//vector<info> G[maxn];
void dfs(int u, int fa, int bob, int road)//传进去road,但是dp的值没有加上road,因此最值判断要带上road.
{
if(head[u]==-1)//叶子节点
{
if(road <= r&&road>=l)//能够提供情况
{
dp[u] = 0;
}
else//不能提供情况
{
dp[u] = -1;
}
return;
}
if(bob)
{
dp[u] = -1;
for(int i = head[u];i !=-1;i = edge[i].next)
{
int v = edge[i].to, len = edge[i].len;
if(v!=fa)
{
dfs(v, u, 1-bob, road + len);
if(dp[v]==-1)//有效情况
continue;
int t = dp[v] + len;
if(t + road >=l&&t+road<=r)//有效情况
{
dp[u] = max(dp[u], t);
}
}
}
if(dp[u] + road > r||dp[u]+road < l)//没有有效的情况
{
dp[u] = -1;
}
}
else//一样的
{
dp[u] = INF;
for(int i = head[u];i!=-1;i = edge[i].next)
{
int v = edge[i].to, len = edge[i].len;
if(v!=fa)
{
dfs(v, u, 1-bob, road+len);
if(dp[v]==-1)
continue;
int t = dp[v] + len;
if(t + road >=l&&t+road<=r)
{
dp[u] = min(dp[u], t);
}
}
}
//        if(road <= r&&road >= l)
//        {
//            dp[u] = 0;
//        }
if(dp[u]==INF)
{
dp[u] = -1;
}
}
}
void solve()
{
dfs(0, -1, 1, 0);
if(dp[0] == -1)
{
printf("Oh, my god!\n");
}
else
{
printf("%d\n", dp[0]);
}
}
int read()//快速读入
{
char ch;
int ans = 0;
ch = getchar();
while(!(isdigit(ch)))
{
ch = getchar();
}
while(isdigit(ch))
{
ch = ch-'0';
ans = ch+(ans << 3) + (ans << 1);
ch = getchar();
}
return ans;
}
int main()
{
//  freopen("6Fin.txt", "r", stdin);
//freopen("6Fout.txt", "w", stdout);
while(scanf("%d%d%d", &n, &l, &r) == 3)
{
memset(head, -1 , sizeof(head));
tot = 0;
REP_D(i, 1, n - 1)
{
int a, b, len;
a = read();
b = read();
len = read();
//scanf("%d%d%d", &a, &b, &len);
//            info t;
//            t.to = b;
//            t.len = len;
//            G[a].push_back(t);
//            t.to = a;
//            G[b].push_back(t);
add_edge(a, b, len);
}
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: