0x54 树形DP
树形DP我只知道千万别写森林转二叉树慢的要死
没有上司的舞会 水!裸!
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; struct node
{
int x,y,next;
}a[];int len,last[];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
} int f[][],h[];
void treedp(int x)
{
f[x][]=;f[x][]=h[x];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
treedp(y);
f[x][]+=max(f[y][],f[y][]);
f[x][]+=f[y][];
}
} int fa[];
int main()
{
int n,x,y;
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&h[i]);
for(int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
ins(y,x);fa[x]=y;
} int rt;
for(int i=;i<=n;i++)
if(fa[i]==)rt=i;
treedp(rt);
printf("%d\n",max(f[rt][],f[rt][]));
return ;
}
没有上司的舞会
选课 带个背包咯,注意一下背包别重复用一个子节点就好
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; struct node
{
int x,y,next;
}a[];int len,last[];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
} int f[][],h[],tot[];
void treedp(int x)
{
f[x][]=h[x];tot[x]=;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
treedp(y);
for(int i=tot[x];i>=;i--)
for(int j=tot[y];j>=;j--)
f[x][i+j]=max(f[x][i+j],f[x][i]+f[y][j]);
tot[x]+=tot[y];
}
} int fa[];
int main()
{
int n,m,x,y;
scanf("%d%d",&n,&m);
h[]=;
for(int i=;i<=n;i++)
{
scanf("%d%d",&fa[i],&h[i]);
ins(fa[i],i);
}
memset(f,-,sizeof(f));
treedp();
printf("%d\n",f[][m+]);
return ;
}
选课
poj3585 这题还挺有意思哈,书上说这是“不定根”的树形DP问题,有个很高大上的名词叫二次扫描与换根法
其实自己YY一下,设1为根,第一次dfs把每个点管辖的子树的流量d算出来,对于一个点其实它的流量就是这个d值+从父节点流出去的流量,画个图还是很好解决的,就是min(到父节点的边权,父节点的d值-当前点给父节点的贡献)
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; struct node
{
int x,y,c,next;
}a[];int len,last[];
void ins(int x,int y,int c)
{
len++;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len;
} bool checkleaf(int x,int fr)
{
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fr)return false;
}
return true;
} int d[];
void dfs(int x,int fr)
{
d[x]=;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fr)
{
dfs(y,x);
if(checkleaf(y,x)==true)d[x]+=a[k].c;
else d[x]+=min(a[k].c,d[y]);
}
}
}
int mmax;
void solve(int x,int fr,int rd)
{
mmax=max(mmax,d[x]+rd);
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fr)
{
int g;
if(checkleaf(y,x)==true)g=d[x]-a[k].c;
else g=d[x]-min(a[k].c,d[y]); if(checkleaf(x,y)==true)solve(y,x,a[k].c);
else solve(y,x,min(rd+g,a[k].c));
}
}
} int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
int n,x,y,c;
scanf("%d",&n);
len=;memset(last,,sizeof(last));
for(int i=;i<n;i++)
{
scanf("%d%d%d",&x,&y,&c);
ins(x,y,c);ins(y,x,c);
}
dfs(,);
mmax=;solve(,,);
printf("%d\n",mmax);
}
return ;
}
poj3585
0x54 树形DP的更多相关文章
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- bzoj2500: 幸福的道路(树形dp+单调队列)
好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...
随机推荐
- Android使用charles抓包
1.下载并安状软件,官网在此: 2.前题条件,电脑和手机必须在同一网段 3.在Charles界面选择菜单 proxy->proxy settings 勾选"Enable transpa ...
- Visual C++ 6.0的界面介绍
双击Visual C++ 6.0安装目录下的文件启动Visual C++ 6.0,通过“文件”→“新建”可新建一个Win32 Console Application项目.创建好项目后,显示Visu ...
- SQL Server对数据进行修改
SQL Server对数据进行修改,修改数据库中的数据. auto"> <tr style="background:red"> <td>编号 ...
- [Intermediate Algorithm] - Finders Keepers
题目 写一个 function,它浏览数组(第一个参数)并返回数组中第一个通过某种方法(第二个参数)验证的元素. 提示 Array.filter() 测试用例 find([1, 3, 5, 8, 9, ...
- CodeForces 356A_(set应用,线段树)
A. Knight Tournament time limit per test 3 seconds memory limit per test 256 megabytes input standar ...
- 范畴论-一个单子(Monad)说白了不过就是自函子范畴上的一个幺半群而已
范畴即为结构:包含要素和转化. 范畴为高阶类型. 函子为高阶函数.函子的输入为态射.函子为建立在态射基础上的高阶函数.函子用于保持范畴间映射的结构.态射用于范畴内部的转换. 群为运算规则的约束. 自函 ...
- springMvc学习地址新
http://www.admin10000.com/document/6436.html 一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar ...
- tomcat配置SSH加密
[root@tomcat2 ~]# keytool -genkeypair -alias tomcat -keyalg RSA -keystore /usr/local/tomcat7/keystor ...
- jsp 多条件组合查询
web层: public String query(HttpServletRequest request, HttpServletResponse response) throws ServletEx ...
- Python对JSON的操作 day3
下面将为大家介绍如何使用python语言来编码和解码json对象: json串就是一个字符串,json串必须用双引号,不能使用单引号 使用json函数需要导入json库,import json 1.j ...