思路:首先声明我是参考: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. 四轴飞行diy全套入门教程(从最基础的开始)

    转载:http://www.cnmox.com/thread-12460-1-1.html首先声明本人也是菜鸟,此教程就是从一个菜鸟的角度来讲解,现在论坛上的帖子都突然冒很多名词出来,又不成体系,我自 ...

  2. mysql的interval函数用法

    Name: 'INTERVAL' Description: Syntax: INTERVAL(N,N1,N2,N3,...) Returns 0 if N < N1, 1 if N < N ...

  3. mount nfs的可选参数

    mount nfs的可选参数:HARD mount和SOFT MOUNT:HARD:NFS CLIENT会不断的尝试与SERVER的连接(在后台,不会给出任何提示信息,在LINUX下有的版本仍然会给出 ...

  4. 深入Mysql 导入导出

    mysql常用导出数据命令:1.mysql导出整个数据库  mysqldump -hhostname -uusername -ppassword databasename > backupfil ...

  5. HDOJ 1151 Air Raid

    最小点覆盖 Air Raid Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  6. C++为什么不支持某些东西

    1.学习C++的过程,经常发现C++不支持一些东西,思考下,为什么? 2.C++不支持一些东西,有两个原因: a.可以做到,但是会导致一些不合理的结果,这些结果往往与程序员的期望不一致. b.属于“臣 ...

  7. Codeforces Round #329 (Div. 2) B. Anton and Lines 逆序对

    B. Anton and Lines Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/593/pr ...

  8. .NET中的三种Timer的区别和用法

    最近正好做一个WEB中定期执行的程序,而.NET中有3个不同的定时器.所以正好研究研究.这3个定时器分别是: //1.实现按用户定义的时间间隔引发事件的计时器.此计时器最宜用于 Windows 窗体应 ...

  9. 飘逸的python - 编码杂症之在字符串前面加u

      有时候我们从其它地方接受的字符串经过艰难跋涉,它变了个样.比如收到的是'\u6253\u602a\u8005'而不是u'\u6253\u602a\u8005'. 明明肉眼看起来只需要加个u,但是怎 ...

  10. C++ C++ 控制台程序 设置图标

    . 实现过程 创建1个控制台程序. 新建1个 Resource Script文件 #include "stdio.h" #include <windows.h> #in ...