算法:poj 3107 Godfather(树形dp)

题意

给一颗n个结点的树,节点编号为1~n,问删除一个节点之后,让剩下的分支中节点数量最多的尽

量少。

可能有多种方案,按编号顺序输出。

思路

简单的树形dp. 其实连dp都不能算吧...就是直接

计数统计

先dfs计算每个节点子树的节点个数tot[i]。

再次dfs更新答案:

f[i] = max( n-tot[i],

max{tot[v] | v是i的儿子} );

两个dfs可以合并在一个dfs里完成, 复杂度O(n)

代码

/**=====================================================
* This is a solution for ACM/ICPC problem
*
* @source : poj-3107 Godfather
* @description : 树形dp
* @author : shuangde
* @blog : blog.csdn.net/shuangde800
* @email : zengshuangde@gmail.com
* Copyright (C) 2013/08/30 16:26 All rights reserved.
*======================================================*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;

typedef pair<int, int >PII;
typedef long long int64;
const int INF = 0x3f3f3f3f;

const int MAXN = 50010;
int tot[MAXN];
int f[MAXN], minx;

namespace Adj {
int size, head[MAXN];
struct Node{
int v, next;
}E[MAXN*2];
inline void initAdj() {
size = 0;
memset(head, -1, sizeof(head));
}
inline void addEdge(int u, int v) {
E[size].v = v;
E[size].next = head[u];
head[u] = size++;
}
}
using namespace Adj;

int n;

int dfs(int u, int fa) {

tot[u] = 1;
// count
// http://www.bianceng.cn
for (int e = head[u]; e != -1; e = E[e].next) {
int v = E[e].v;
if (v == fa) continue;
tot[u] += dfs(v, u);
}
// 计算答案
int& ans = f[u] = n - tot[u];
for (int e = head[u]; e != -1; e = E[e].next) {
int v = E[e].v;
if (v == fa) continue;
ans = max(ans, tot[v]);
}
minx = min(minx, ans);
return tot[u];
}

int main(){

while (~scanf("%d", &n)) {

initAdj();
for (int i = 0; i < n - 1; ++i) {
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}

minx = INF;
dfs(1, -1);

bool first = true;
for (int i = 1; i <= n; ++i)
if (f[i] == minx) {
if (first) first = false, printf("%d", i);
else printf(" %d", i);
}
puts("");
}
return 0;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, include
, dfs
, 节点
, head
树形
树形dp、树形dp入门、bzoj 树形dp、poj树形dp、树形dp专题,以便于您获取更多的相关知识。

时间: 2024-10-03 00:38:27

算法:poj 3107 Godfather(树形dp)的相关文章

算法:poj 2378 Tree Cutting(树形dp)

题意 给一颗n个结点的树,节点编号为1~n,把删除一个节点之后, 剩下的分支中节点数量最多的数 量不大于总数量一半的编号全部按顺序输出 思路 和poj-3107 GodFather完全一样,只是输出不一样. 改为<=n/2的就输出即可. 代码 /**===================================================== * This is a solution for ACM/ICPC problem * * @source : poj-2378 Tree C

算法:poj 4045 Power Station (树形dp)

题意 n个城市节点构成的一棵树,节点i到节点j的电量损耗为 I*I*R*(i到j的路径所含边数),现 在要在某个结点上修建一个供电站,使得这个结点到所有其它节点的总损耗量最小. 思路 典型的树形dp 可以先用一次dfs求出每一点的子树结点个数num[u],以及每一点到它子树所有结点的总 距离f[u][0]; 然后再用一次dfs,推出每个结点到除去它子树部分的结点总距离f[u][1]. f[v][1] = (f[u][0]-f[v][0]-num[v]) + f[u][1] + n - num[v

算法:poj 1655 Balancing Act(树形dp)

题意 一n个节点的棵树,去掉某个节点后,会变成一个森林. 这个森林中的每个树都有个节点数量, 其中最大节点数设为max 问删除某个节点后,max最小可以多少? 思路 和poj-3107 GodFather完全一样! 不想吐槽了... 其实本来不想发这篇,不过发现今天是八月最后一天,而且 还差一篇就发了80篇了..于是..就很邪恶的水了 代码 /**===================================================== * This is a solution

算法:poj 3140 Contestants Division(树形dp? dfs计数+枚举)

题目 给n个节点的带权树,删掉其中一边,就会变成两颗子树, 求删去某条边使得这这两颗子树的 权值之差的绝对值最小. 思路 直接dfs一次,计算所有子树的权值总和tot[i] 如果删掉一条边 (v, fa),fa是v的父亲节点, 那么v子树权值总和为tot[v],显然另一棵子树的权值总和就是sum-tot[v] , 最总取最小绝对值即可. 这题要注意用long long 其实就是dfs+枚举,想不通为什么有人会 把这题列为树形dp? 代码 /**==========================

算法:ural 1018 Binary Apple Tree(树形dp | 经典)

题意 给一棵边有权值的二叉树,节点编号为1-n,1是根节点.求砍掉一些边,只保留q条边,这q条边 构成的子树 的根节点要求是1,问这颗子树的最大权值是多少? 思路 非常经典的一道树形dp题 ,根据我目前做过的题来看,有多道都是由这题衍生出来的. f(i, j) 表示子树i,保留j个节点(注意是 节点)的最大权值.每条边的权值,把它看作是连接的两个节点中的儿子节点的权值. 那么,就可以对所 有i的子树做分组背包,即每个子树可以选择1,2,...j-1条边分配给它. 状态转移为: f(i, j) =

算法:uva 10859 Placing Lampposts (树形dp)

题目大意 给你一个n个点m条边的无向无环图,在尽量少的节点上放灯,使得所有边都被照亮. 每盏灯将照亮以它为一个端点的所有边. 在灯的总数最小的前提下,被两盏灯同时被照亮的边数应该 尽量大. 思路 这是LRJ<训练指南>上的例题. 这题教会了我一个很有用的技巧:有 两个所求的值要优化,比如让a尽量小,b也尽量小 那么可以转化为让 M*a+b尽量小,其中M应该是 一个比"a的最大值和b的最小值之差"还要大的数 最终的答案为ans/M, ans%M 回到这题,要 求放的灯总数最小

算法:zoj-3626 Treasure Hunt I (树形dp)

题意 给一棵n个节点的树, 节点编号1~n, 每个节点有权值val[i],经过这个节点就可以获取这个价值( 不能重复获得) 每一条边有一个花费值w(i,j), 表示走完i和j点的边要花费w(i,j) 现在要从k点出发, 总花费值为m,问总花费不超过m的情况下并且最终要回到出发点,最多可以获取多少价值? 思路 简单树形dp. f(i,j)表示子树i, 用花费j最多可以获得的价值 对与i的每个儿子,可以选择分配花费 2*w, 2*w+1, 2*w+2,...j给它,可以看作是一组物品 对所有儿子做分

算法:uva 1484 Alice and Bob&#039;s Trip (树形dp)

题意 给一棵n个结点的树,结点编号为0~n-1,顶点是0 每条边都有一个权值. Alice和Bob初始位 置在顶点,要往下一直走到叶子结点. 第一次是由Bob选择走向哪个子结点,第二次轮到Alice,依次轮流 下去... 每走过一条边就会获得相应的权值,Bob希望所走的路径总权值越大越好,而Alice希望越小越好 每次他们都会选择最优解. 最终总权值要在范围[L,R]之内. 问最终Bob希望的最大权值是多少? 思路 f(u, 0)表示第u点由Bob选时的最大值 f(u, 1)表示第u点由Alic

算法:HDU 4679 Terrorist’s destroy(树形dp | 多校8)

题意 给一棵树,每条边有个权值,要删掉一条边,删掉以后会变成两颗子树,设两个子树的直径分别 为d1, d2,删掉的这条边权值为w 问删掉哪一条边,使得w*max(d1, d2)的值最小? 思路 典型的 树形dp, 但比赛时的代码写得非常搓,200+行,还好1A了 f(u, 0):以u点为顶点的子树的直径 f (u, 1):以u的父节点为顶点减去u的子树部分的子树的直径 先用树形dp求出上面的数组 然后 答案等于 min{ w(u,v)*max{f(v,0), f(v,1)} | v为u的子节点