bzoj 1907: 树的路径覆盖【贪心+树形dp】

我是在在做网络流最小路径覆盖的时候找到这道题的

然后发现是个贪心+树形dp

\( f[i] \)表示在\( i \)为根的子树中最少有几条链,\( v[i] \) 表示在\( i \)为根的子树中\( i \) 是( 0)否(1)为一条链的端点

然后贪心转移即可(有链端点则连起来)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=10005;
int T,n,h[N],cnt,f[N];
bool v[N];
struct qwe
{
    int ne,to,va;
}e[N<<1];
void add(int u,int v)
{
    cnt++;
    e[cnt].ne=h[u];
    e[cnt].to=v;
    h[u]=cnt;
}
void dfs(int u,int fa)
{
    int con=0;
    f[u]=1;
    for(int i=h[u];i;i=e[i].ne)
        if(e[i].to!=fa)
        {
            dfs(e[i].to,u);
            f[u]+=f[e[i].to];
            if(!v[e[i].to])
                con++;
        }
    if(con==1)
        f[u]--;//减掉本身
    else if(con>1)
        f[u]-=2,v[u]=1;//减掉本身和其中一个端点
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(h,0,sizeof(h));
        memset(e,0,sizeof(e));
        memset(f,0,sizeof(f));
        memset(v,0,sizeof(v));
        cnt=0;
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1,0);
        printf("%d\n",f[1]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/lokiii/p/8185892.html

时间: 2024-10-05 20:55:17

bzoj 1907: 树的路径覆盖【贪心+树形dp】的相关文章

bzoj 1907 树的路径覆盖 贪心

题面 题目传送门 解法 给个链接,贪心和树形dp讲得挺到位的 题解 反正我觉得贪心比较好写,也挺好理解的 时间复杂度:\(O(Tn)\) 代码 #include <bits/stdc++.h> #define N 10010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x, y);} template <typename node> voi

BZOJ 1907 树的路径覆盖 树形DP

题目大意:给定一棵树,求最小路径覆盖 数据范围1W,看到还想跑网络流来着= = 不过算了明明树形DP这么水还是不要用网络流这种大杀器为好 首先将所有的链都考虑成以链上所有点的LCA为转折点的V字形 那么点有两种:转折点和非转折点 因此我们选择两种状态进行转移:还会和父亲组成链的状态和成为转折点的状态 转移就自己YY算了 时间复杂度是线性的 #include <cstdio> #include <cstring> #include <iostream> #include

1907: 树的路径覆盖

1907: 树的路径覆盖 Time Limit: 5 Sec  Memory Limit: 259 MBSubmit: 506  Solved: 219[Submit][Status][Discuss] Description Input Output Sample Input 1 7 1 2 2 3 2 4 4 6 5 6 6 7 Sample Output 3 HINT Source Play with Tree By Amber 题解:贪心题么么哒,直接DFS一遍就好啦 1 /******

【bzoj1907】树的路径覆盖 树形dp

题目描述 输入 输出 样例输入 1 7 1 2 2 3 2 4 4 6 5 6 6 7 样例输出 3 题解 树形dp 设f[x]表示以x为根的子树完成路径覆盖,且x为某条路径的一端(可以向上延伸)的最小路径数,g[x]表示以x为根的子树完成路径覆盖,且x不为某条路径的一端的最小路径数. 那么考虑点x,只有三种情况:单独成路径.与一条子树的链成路径.与两条子树的链成路径. 这三种情况分别对应三种状态转移方程,具体见代码. 然而看到网上题解大把大把的贪心我也是醉了qaq #include <cstd

BZOJ1907 树的路径覆盖

ydc题解上写着贪心,后来又说是树形dp...可惜看不懂(顺便骗三连) 其实就是每个叶子开始拉一条链,从下面一路走上来,遇到能把两条链合起来的就合起来就好了. 1 /************************************************************** 2 Problem: 1907 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:112 ms 7 Memory:1396 kb 8 *****

【BZOJ2286】消耗战(虚树,DFS序,树形DP)

题意:一棵N个点的树上有若干个关键点,每条边有一个边权,现在要将这些关键点到1的路径全部切断,切断一条边的代价就是边权. 共有M组询问,每组询问有k[i]个关键点,对于每组询问求出完成任务的最小代价. 对于100%的数据,2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1 思路:第一题虚树,需要详细地记录一下. 对于此题,朴素的树形DP很好理解: dp[u]为将u子树中的关键点全部切断的最小代价 dp[u]=min(cut[u]

将军令(贪心&amp;&amp;树形DP)

只看45分的话,是树形DP....(当然也有能拿到70分+的大佬) 40分: 只考虑k==1的情况,树形DP 所以每个节点可能被父亲,自己,儿子控制 设f[MAXN][3],0表示儿子,1表示自己,2表示父亲 f[i][1]+=min(f[to][0],f[to][1],f[to][2])(因为自己控制自己,儿子怎样都行) f[i][0]+=min(f[to][0],f[to][1]) 但是因为i的儿子必须有一个自己控制自己,所以还要判断所加值中是否有f[to][1],如果没有 f[i][0]+

BZOJ 1040 ZJOI 2008 骑士 基环树林+树形DP

题目大意:有一些骑士,他们每个人都有一个权值.但是由于一些问题,每一个骑士都特别讨厌另一个骑士.所以不能把他们安排在一起.求这些骑士所组成的编队的最大权值和是多少. 思路:首先貌似是有向图的样子,但是一个人讨厌另一个人,他们两个就不能在一起,所以边可以看成是无向的. n个点,n条无向边,好像是一颗基环树.但其实这是一个基环树林,因为题中并没有说保证图一定联通. 然后就可以深搜了,处理出每一个联通块.其实每一个联通块就是一个基环树,在这个基环树上进行树形DP.求出最大值,然后累加到答案上.答案要开

[BZOJ 1017][JSOI2008]魔兽地图DotR(树形Dp)

Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars.DotR里面的英雄只有一个属性——力量.他们需要购买装备来提升自己的 力量值,每件装备都可以使佩戴它的英雄的力量值提高固定的点数,所以英雄的力量值等于它购买的所有装备的力 量值之和.装备分为基本装备和高级装备两种.基本装备可以直接从商店里面用金币购买,而高级装备需要用