您的位置:首页 > 其它

uvalive 5088 hdu3066(树形dp)

2017-04-06 00:39 429 查看
题意:给出一棵n个结点的树,两个人一起走,轮流决策 Alice目的是使最后距离最小 Bob相反

问最终走的距离能否满足区间[L,R]

(需要走到最后不能走,所以Alice不能不选就结束了)

如果没有[L,R],直解dfs,Bob的话选最大儿子走,Alice选最小儿子走

现在多了[L,R],选的时候,就需要判断满足总距离(是总距离!!即答案)满足[L,R]然后再选最大/小

在结点u判断选择是否满足条件时,需要多记录一个dist[u]表示从根0到u的距离

if(dist[u] + dp[v] + w <= R && dist[u] + dp[v] + w >= L)

才更新答案

启示:知道某个节点,就知道了根0到它的距离以及轮到谁决策

这是很有用的性质,最终答案就是 dist[u]+dp[v]+w

转:http://www.cppblog.com/Yuan/archive/2010/10/03/128074.html?opt=admin

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define clr(x) memset(x,0,sizeof(x))
#define maxn 500005
struct node
{
int v,next,w;
}edge[10000000];
int tot;
int head[maxn];
int n,L,R;
int dp[maxn];
int d[maxn];
void add(int a,int b,int c)
{
edge[tot].v=b;
edge[tot].w=c;
edge[tot].next=head[a];
head[a]=tot++;
}

void dfs(int x,int
4000
p)
{
if(d[x]>R)
{
dp[x]=0;
return ;
}
int flag=1;
dp[x]=p?-1:INF;
for(int i=head[x];~i;i=edge[i].next)
{ //对每个能到这里的点的路径进行dp的更新,因为每次到这个结点的父子结点不一定一样,
//那么从叶子确定到不同的k也不一样
int k=edge[i].v;//dp[k]为从叶子结点到当前结点的长度。
d[k]=d[x]+edge[i].w;//d[k]初始化为0到k的长度
dfs(k,!p);//往下搜索,往上回溯
int tmp=d[k]+dp[k];//计算整个路径的长度
if(tmp>=L&&tmp<=R)
{
if(p)
dp[x]=max(dp[x],dp[k]+edge[i].w);
else
dp[x]=min(dp[x],dp[k]+edge[i].w);
}
}
if(flag)
{
dp[x]=0;
}
}

int main()
{
int i;
while(scanf("%d%d%d",&n,&L,&R)!=EOF)
{
tot=1;
memset(head,-1,sizeof(head));
for(int i=1;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
memset(d,0,sizeof(d));
dfs(0,1);
if(dp[0]>=L&&dp[0]<=R)
printf("%d\n",dp[0] );
else printf("Oh, my god!\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: