描述

给定一颗树(边权为1),选取一个节点子集,使得该集合中任意两个节点之间的距离都大于K。求这个集合节点最多是多少

输入

第一行是两个整数N,K

接下来是N-1行,每行2个整数x,y,表示x与y有一条边

输出

1个整数表示最多的节点数

样例输入

3 1

1 2

1 3

样例输出

2

提示

测试点 N的上限 K 特征
1 15 1
2 1000 1
3 1000 1
4 100000 1
5 100000 1
6 15 2
7 1000 2
8 1000 2
9 100000 2
10 100000 2

树形dp入门题。

T=2的情况有点意思。

设当前访问第i个节点。

f[i][0]" role="presentation" style="position: relative;">f[i][0]f[i][0]:i不选但i父亲选。

f[i][1]" role="presentation" style="position: relative;">f[i][1]f[i][1]:不选且i父亲不选。

f[i][2]" role="presentation" style="position: relative;">f[i][2]f[i][2]:i选。

显然有:

f[i][2]=1+∑vf[v][0]" role="presentation" style="position: relative;">f[i][2]=1+∑vf[v][0]f[i][2]=1+∑vf[v][0]

以及:

f[i][0]=∑vf[v][1]" role="presentation" style="position: relative;">f[i][0]=∑vf[v][1]f[i][0]=∑vf[v][1]

关键是f[i][1]" role="presentation" style="position: relative;">f[i][1]f[i][1]

这个东西需要考虑儿子之间是否冲突,因此最优值的产生有两种可能:

1. 所有儿子都不选。

2. 某一个儿子选,其余不选。

因此有f[i][1]=(∑vf[v][1])+max(0,f[v][2]−f[v][1])" role="presentation" style="position: relative;">f[i][1]=(∑vf[v][1])+max(0,f[v][2]−f[v][1])f[i][1]=(∑vf[v][1])+max(0,f[v][2]−f[v][1])。

代码:

#include<bits/stdc++.h>
#define N 100005
using namespace std;
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans;
}
int first[N],n,k,cnt=0,f[N][3];
struct edge{int v,next;}e[N<<1];
inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;}
inline int max(int a,int b){return a>b?a:b;}
inline int dfs1(int p,bool k,int fa){
    if(f[p][k]!=-1)return f[p][k];
    f[p][k]=k;
    for(int i=first[p];i;i=e[i].next){
        int v=e[i].v;
        if(v==fa)continue;
        if(!k)f[p][k]+=max(dfs1(v,0,p),dfs1(v,1,p));
        else f[p][k]+=dfs1(v,0,p);
    }
    return f[p][k];
}
inline int dfs2(int p,int k,int fa){
    if(f[p][k]!=-1)return f[p][k];
    f[p][k]=(k==2);
    if(!k){
        for(int i=first[p];i;i=e[i].next){
            int v=e[i].v;
            if(v==fa)continue;
            f[p][k]+=dfs2(v,1,p);
        }
    }
    else if(k==1){
        int max1=0;
        for(int i=first[p];i;i=e[i].next){
            int v=e[i].v;
            if(v==fa)continue;
            f[p][k]+=dfs2(v,1,p);
            int tmp=dfs2(v,2,p)-dfs2(v,1,p);
            if(max1<tmp)max1=tmp;
        }
        f[p][k]+=max1;
    }
    else for(int i=first[p];i;i=e[i].next){
        int v=e[i].v;
        if(v==fa)continue;
        f[p][k]+=dfs2(v,0,p);
    }
    return f[p][k];
}
int main(){
    n=read(),k=read();
    for(int i=1;i<n;++i){
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    memset(f,-1,sizeof(f));
    if(k==1)cout<<max(dfs1(1,1,1),dfs1(1,0,1));
    else cout<<max(dfs2(1,1,1),dfs2(1,2,1));
    return 0;
}

2018.09.01 独立集(树形dp)的更多相关文章

  1. 2018.09.01 loj#2330. 「清华集训 2017」榕树之心(树形dp)

    传送门 树形dp好题啊. 我们用w[i]" role="presentation" style="position: relative;">w[ ...

  2. P4383 [八省联考2018]林克卡特树 树形dp Wqs二分

    LINK:林克卡特树 作为树形dp 这道题已经属于不容易的级别了. 套上了Wqs二分 (反而更简单了 大雾 容易想到还是对树进行联通情况的dp 然后最后结果总和为各个联通块内的直径. \(f_{i,j ...

  3. 2018.09.01 poj3071Football(概率dp+二进制找规律)

    传送门 概率dp简单题. 设f[i][j]表示前i轮j获胜的概率. 如果j,k能够刚好在第i轮相遇,找规律可以发现j,k满足: (j−1)>>(i−1)" role=" ...

  4. 2018.09.01 hdu4405 Aeroplane chess (期望dp)

    传送门 期望dp简单题啊. 不过感觉题意不太对. 手过了一遍样例发现如果有捷径必须走. 这样的话就简单了啊. 设f[i]" role="presentation" sty ...

  5. 2018.09.01 09:22 Exodus

    Be careful when writing in the blog garden. Sometimes you accidentally write something wrong, and yo ...

  6. 2018.09.01 09:08 Genesis

    Nothing to think about, I don't know where to start, the mastery of learning is not an easy task, yo ...

  7. 2018.09.01 poj2689 Prime Distance(埃式筛法)

    传送门 一道挺有趣的. 第一眼以为每个数都用miller_rabin判一次,但感觉会被卡时间啊. 继续分析发现可以晒出sqrt(r)中的所有素数,然后用类似埃式筛法的方法晒出[l,r]" r ...

  8. 2018.09.14 洛谷P3931 SAC E#1 - 一道难题 Tree(树形dp)

    传送门 简单dp题. f[i]表示以i为根的子树被割掉的最小值. 那么有: f[i]=min(∑vf[v],dist(i,fa))" role="presentation" ...

  9. 2018.09.06 警卫安排(树形dp)

    描述 太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫. 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状:有边直接相连的宫殿可以互相望见.大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全 ...

随机推荐

  1. js实现点击按钮弹出上传文件的窗口

    转自:https://www.jb51.net/article/100916.htm 1.详细描述 在页面上设置一个“选择文件”按钮,点击该按钮,会弹出本地磁盘信息用于选择文件. 2.代码 ? 1 2 ...

  2. JSON.Stringify()和JSON.parse()的比较使用

    1.  JSON.Stringify() 将一个对象解析成字符串 <script> function myonclick() { var value = $('select option: ...

  3. AS3中String转换成Boolean

    AS3中, 对布尔值的转换, 规定所有的非空字符串都是true. 下面都不行: var f:Boolean = new Boolean(str); var f:Boolean = str as Boo ...

  4. 前段开发-css-总结

    应用参考https://www.cnblogs.com/alice-bj/p/8972299.html CSS:层叠样式表(Cascading Style Sheets) 1.css的特征 一.css ...

  5. conflicting types for ‘方法名’ 的错误

    将main()的实现写在drawShapes(),drawCircle(),drawRectangle()...之前. 结果编译的时候出现了  conflicting types for " ...

  6. How to Pronounce ‘to the’ in a Sentence

    How to Pronounce ‘to the’ in a Sentence Share Tweet Share Tagged With: The Word THE, TO Reduction St ...

  7. 迷你MVVM框架 avalonjs 学习教程21、双向绑定链

    avalon的双向绑定机制,是通过一条依赖链实现.此依赖链最底层是监控属性.监控数组,中层是计算属性.监控函数,再上点是求值函数,最上层是视图刷新函数. 所谓计算属性,监控属性,监控函数属性,我们改变 ...

  8. javascript 函数对象

    http://hi.baidu.com/gdancer/blog/item/a59e2c12479b4e54f919b814.html jQuery的一些写法就是基于这篇文章的原理的..     函数 ...

  9. 吴裕雄 数据挖掘与分析案例实战(15)——DBSCAN与层次聚类分析

    # 导入第三方模块import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as snsfr ...

  10. 数据文件导入mysql时出现中文乱码问题

    http://www.ynpxrz.com/n773257c2024.aspx 从shell进入mysql, mysql> show variables like ‘%char%'; +---- ...