思路:首先声明我是参考:http://blog.csdn.net/frog1902/article/details/9921845这位大牛的博客的。

他说的已经很详尽,但我还是要补充几点。

看完他的解题报告在看我的才好些。

我这的back[i]对于他的lim[i]。

我要补充的是,back[i]不是真正的back[i],可以看到这行代码:back[u]=max(back[u],dep[v]+1);也就是说是其返回祖节点再往下的一个节点。

对于没有回退边的点,其back[i]==0相当于有一个回退边到根节点,那么本节点到根节点上的任何一条边被选择都是可行的。

dp时,首先将dp[u][i](back[u]<=i<=dep[u])置为0,意义是如果在u到back[u]之间已经有一条边被其他节点选择了,那么其不考虑有子节点的话,需要的边数就是0。dp[u][dep[u]]++的意义是选择dep[u]到其父节点的边的点正是u自己。

我个人认为最难理解的是对于dp[u][j],要从dp[v][dep[v]]与0<=k<=j的深度中选取最小的dp[v][k]求和作为dp[u][j]的值。

由于dp[u][j]的意义是选择了深度为j的节点到其父节点的边后,以u为根的子树仍需要多少边,那么可以这个值也就是选择了深度为j的节点到其父节点的边后,以其子节点为根还需要dp[v][j]已经确定,那么自然以u为根的需要边数就是其子节点需要边数的和(前提是所有的选边一定要合法,合法的就是这条边一定要在back[u]到u的路径上)。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#define Maxn 2010
using namespace std;
int dp[Maxn][Maxn],dep[Maxn],back[Maxn],n,m,vi[Maxn];
vector<int> head[Maxn];
void init()
{
memset(dp,-,sizeof(dp));
memset(dep,,sizeof(dep));
memset(vi,,sizeof(vi));
memset(back,,sizeof(back));
for(int i=;i<=n;i++)
head[i].clear();
}
void add(int u,int v)
{
head[u].push_back(v);
head[v].push_back(u);
}
void dfs(int u)
{
int i,v,sz;
vi[u]=;
sz=head[u].size();
for(i=;i<sz;i++)
{
v=head[u][i];
if(vi[v]) continue;
dep[v]=dep[u]+;
dfs(v);
}
}
void Treedp(int u)
{
int i,v,sz,j;
vi[u]=;
sz=head[u].size();
for(i=back[u];i<=dep[u];i++)
dp[u][i]=;
for(i=;i<sz;i++)
{
v=head[u][i];
if(vi[v]) continue;
Treedp(v);
int temp=dp[v][dep[v]];
for(j=;j<=dep[u];j++)
{
if(dp[v][j]!=-)
{
if(temp!=-)
temp=min(temp,dp[v][j]);
else
temp=dp[v][j];
}
if(j>=back[u])
{
if(temp!=-)
dp[u][j]+=temp;
}
}
}
if(u!=)
dp[u][dep[u]]++;
}
int main()
{
int i,j,u,v;
while(scanf("%d%d",&n,&m)!=EOF,n||m)
{
init();
for(i=;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
}
dfs();
for(i=n;i<=m;i++)
{
scanf("%d%d",&u,&v);
if(dep[u]<dep[v])
swap(u,v);
back[u]=max(back[u],dep[v]+);
}
memset(vi,,sizeof(vi));
Treedp();
printf("%d\n",dp[][]);
}
return ;
}

hdu 4582 树状DP的更多相关文章

  1. hdu 4679 树状dp

    思路:我们其实只需要枚举每条边,求得最小值就行了. 先dfs算出每个节点作为根时,其子树的最长路径,以及进过该节点的最长,次长,第三长路径. 然后在次dfs枚举求出切断某条边,求出这条边的两个端点为子 ...

  2. hdu 4340 树状DP

    思路:我们定义两个数组,ant[Maxn][2],bob[Maxn][2].ant[i][0]表示还未确定哪个城市被全费用占领,ant[i][1]表示确定了哪个城市被全费用占领.那么ant[i][0] ...

  3. HDU 4035Maze(树状+概率dp,绝对经典)

    题意: 给你n个节点的树,从1节点开始走,到每个节点都有三种情况,被杀死回到1节点,找到隐藏的出口出去,沿着当前节点相邻的边走到下一个节点,给出每个节点三种情况发生的概率分别为ki,ei,1-ki-e ...

  4. hdu 1561 The more, The Better_树状dp

    题目链接 题意:给你一棵树,各个节点都有价值(除根节点),从根节点出发,选择m个节点,问最多的价值是多小. 思路:很明显是树状dp,遍历树时背包最优价值,dp[i][k]=max{dp[i][r]+d ...

  5. HDU 4714 Tree2cycle(树状DP)(2013 ACM/ICPC Asia Regional Online ―― Warmup)

    Description A tree with N nodes and N-1 edges is given. To connect or disconnect one edge, we need 1 ...

  6. 树状DP HDU1520 Anniversary party

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 题意:职员之间有上下级关系,每个职员有自己的happy值,越高在派对上就越能炒热气氛.但是必须是 ...

  7. 树状DP (poj 2342)

    题目:Anniversary party 题意:给出N各节点的快乐指数,以及父子关系,求最大快乐指数和(没人职员愿意跟直接上司一起玩): 思路:从底向上的树状DP: 第一种情况:第i个员工不参与,F[ ...

  8. poj3659树状DP

    Cell Phone Network Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6273   Accepted: 225 ...

  9. poj 2342 Anniversary party_经典树状dp

    题意:Ural大学有n个职员,1~N编号,他们有从属关系,就是说他们关系就像一棵树,父节点就是子节点的直接上司,每个职员有一个快乐指数,现在要开会,职员和职员的直接上司不能同时开会,问怎才能使开会的快 ...

随机推荐

  1. 扩展KMP题目

    hdu4333 /* 题意:字符串s[0..n-1],每次把最后一个字符放到前面,求形成的字符串比最初串分别小,相同,大于的个数 因为是为了练习扩展KMP所以肯定是扩展KMP, 为了循环方便,在后面复 ...

  2. Linux上svn服务器的搭建

    安装svn服务器 直接用yum安装,命令如下: #yum install -y subversion 验证是否安装成功. #svnserve --version 创建SVN版本库 在home目录下创建 ...

  3. poj 1236 Network of Schools(连通图入度,出度为0)

    http://poj.org/problem?id=1236 Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Su ...

  4. [iOS微博项目 - 1.7] - 版本新特性

    A.版本新特性 1.需求 第一次使用新版本的时候,不直接进入app,而是展示新特性界面 github: https://github.com/hellovoidworld/HVWWeibo       ...

  5. [GUI]界面开发类库

    如果我们不十分清楚需要什么样的界面风格及如何实现,请按以下两个步骤操作: (1)       搞清楚这种风格叫什么名字 (2)       查现有的比较著名的GUI库是否已有相应的实现方案. (3)  ...

  6. 访问修饰符与可选修饰符static的使用

    在Java中修饰符较多,在这里简单说一说几个访问修饰符的选择使用,和可选修饰符static的使用. 一.访问修饰符:这是Java里用来控制访问类及类的方法.变量的访问权限,从而达到只暴露接口,来隐藏内 ...

  7. 直接下载Google Play市场的APK

    传送门在这里:http://apps.evozi.com/apk-downloader/ 似乎很方便.很迅速的样子,忍不住在这里记录一下.

  8. C++ 析构方法

    1.什么是析构方法? 析构方法与构造方法互补. 2.为什么设计析构方法? 构造方法创建一个对象,对象内部往往还会申请一些资源.设计析构方法的目的是 释放资源,同时销毁自身. 3.析构方法可以认为分为两 ...

  9. Js Pattern - Self Define Function

    This pattern is useful when your function has some initial preparatory work to do andit needs to do ...

  10. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...