zoukankan      html  css  js  c++  java
  • qbxt Day4

    1.树形dp

    例题1

    树上最长链

    其实有两种方法,但为了简便,就只学了最通用的dp算法

    我们考虑设dp[i][0/1]表示以i为根的最长路和次长路,然后拼接就行了

    第二维0表示最长路,1表示次长路

    if dp[i][0]<dp[son][0] then dp[i][1]=dp[i][0],dp[i][0]=dp[son][0]

    if dp[i][0]>dp[son][0] && dp[i][1]<dp[son][0] then dp[i][1]=dp[son][0]

    就可以了

    例题2

    codevs1378

    有n节课可以选,每节课有至多一个前置课程,和这节课的学分,问如果只能选m节课,最多有多少学分。

    这是一道类似于树形背包的dp

    dp么,需要记录所有可行状态

    考虑设dp[i][j]在以i为根的子树中选除j个课程的最大价值

    每次新增一个儿子,就相当于新增加一个多重背包中的物品。此处暴力枚举就可以了,时间复杂度O(n^3)

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    using std::max;
    using std::min;
    const int maxn=310;
    struct node
    {
    	int point;
    	int nxt;
    };
    node line[maxn<<1];
    int s[maxn];
    int head[maxn],tail;
    int ind[maxn];
    int f[maxn][maxn]; 
    int siz[maxn];
    int n,m;
    void add(int a,int b)
    {
    	line[++tail].point=b;
    	line[tail].nxt=head[a];
    	head[a]=tail;
    }
    void dfs(int now)
    {
    	siz[now]=1;
    	f[now][1]=s[now];
    	for(int i=head[now];i;i=line[i].nxt)
    	{
    		dfs(line[i].point);
    		for(int j=siz[now]+siz[line[i].point];j>=2;j--)
    			for(int k=1;k<=min(siz[line[i].point],j-1);k++)
    			f[now][j]=max(f[now][j],f[now][j-k]+f[line[i].point][k]);
    		siz[now]+=siz[line[i].point]; 
    	}
    } 
    int main() 
    {
    	scanf("%d%d",&n,&m);
    	int dat;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d%d",&dat,&s[i]);
    		add(dat,i);
    	
    	}
    	dfs(0);
    	printf("%d",f[0][m+1]);
    }
    

    例题3

    hdu4679

    给定一颗树,每条边有一个权值w,问切掉哪条边之后,分成的两颗树的较大的直径*切掉边的权值最小?如果存在多条边使得结果相同,输出边id最小的。

    考虑枚举切哪一条边,若不在整棵树的直径上,处理就很好处理

    然后我们考虑如果在直径上呢? 考虑从直径的左右两端点分别为根做一次dp,然后每次切边。将一棵树分成两棵树,这样就可以在o(1)时间内算出分离后两颗子树的直径了

    预处理多么重要呀~~

    例题4

    codeforces219d

    给一棵树,每条边有方向,改变一条边方向的代价是1.

    对于一个点,如果选它为根,那么需要把方向不对的边改变方向(都变成深度小的点指向深度大的点)。

    问选一个点为根的最小代价。和选哪些点的代价是这个数字。

    其实这道题,如果看过平衡树中的rotate操作,其实不难。因为一次换根的时间是O(1)的

    然后先选出一个点来,算出其所需次数,然后将其他点作为根试一次,然后就是O(n)的时间复杂度


    例题4

    bzoj1040

    给一个环套树森林,求最大权独立集。(就是相邻的点不能同时选)

    首先考虑dp一开始考虑做出决策的方法——枚举

    首先每个点只有选与不选,是可以接受的。

    然后我们考虑枚举环上的点,断环为链。再使用树形dp

    但是我们在枚举的时候要枚举相邻的的两个点。防止不合法的情况

    然后我还没有写出来QAQ


  • 相关阅读:
    年轻人要明白,职场里不只有晋升
    为什么我建议年轻人多出去走走?
    聊聊所谓的弹性工作制
    从零开始搭建Java开发环境第四篇:精选IDEA中十大提高开发效率的插件!
    从零开始搭建Java开发环境第三篇:最新版IDEA常用配置指南,打造你的最酷IDE
    ORACLE日期时间函数大全
    我做的 地税信息中心设备台账
    IE8 如何 不显示 选项 卡,直接在任务显示 各个页面?
    分析
    微信端的界面与后台之间的接口稳定性压力测试用什么工具比较好点
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/9333418.html
Copyright © 2011-2022 走看看