BZOJ 2314: 士兵的放置( 树形dp )

树形dp...

dp(x, 0)表示结点x不放士兵, 由父亲控制;

dp(x, 1)表示结点x不放士兵, 由儿子控制;

dp(x, 2)表示结点x放士兵.

-------------------------------------------------------------------------------------

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

typedef long long ll;

const int maxn = 500009;

const int MOD = 1032992941;

struct edge {

int to;

edge* next;

} E[maxn << 1], *pt = E, *head[maxn];

void AddEdge(int u, int v) {

pt->to = v; pt->next = head[u]; head[u] = pt++;

}

void upd0(ll &x, int t) {

if((x += t) >= MOD) x -= MOD;

}

void upd1(ll &x, int t) {

x = x * t % MOD;

}

int N;

ll dp[maxn][3], cnt[maxn][3];

void init() {

scanf("%d", &N);

for(int i = 1; i < N; i++) {

int u, v;

scanf("%d%d", &u, &v);

AddEdge(--u, --v);

AddEdge(v, u);

}

}

void dfs(int x, int fa) {

dp[x][0] = 0; dp[x][1] = maxn; dp[x][2] = 1;

cnt[x][0] = cnt[x][1] = cnt[x][2] = 1;

ll Min, sum;

for(edge* e = head[x]; e; e = e->next) if(e->to != fa) {

dfs(e->to, x);

Min = min(min(dp[e->to][0], dp[e->to][1]), dp[e->to][2]);

sum = 0;

dp[x][2] += Min;

for(int i = 0; i < 3; i++)

if(dp[e->to][i] == Min) upd0(sum, cnt[e->to][i]);

upd1(cnt[x][2], sum);

Min = min(dp[x][1] + min(dp[e->to][1], dp[e->to][2]), dp[x][0] + dp[e->to][2]);

sum = 0;

for(int i = 1; i < 3; i++)

if(dp[x][1] + dp[e->to][i] == Min) upd0(sum, cnt[e->to][i]);

upd1(cnt[x][1], sum);

if(dp[x][0] + dp[e->to][2] == Min)

upd0(cnt[x][1], ll(cnt[x][0]) * cnt[e->to][2] % MOD);

dp[x][1] = Min;

dp[x][0] += dp[e->to][1];

upd1(cnt[x][0], cnt[e->to][1]);

}

}

int main() {

init();

dfs(0, -1);

ll ans = min(dp[0][1], dp[0][2]), sum = 0;

for(int i = 1; i < 3; i++)

if(dp[0][i] == ans) upd0(sum, cnt[0][i]);

printf("%lld\n%lld\n", ans, sum);

return 0;

}

-------------------------------------------------------------------------------------

2314: 士兵的放置

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 114  Solved: 31
[Submit][Status][Discuss]

Description

八中有N个房间和N-1双向通道,任意两个房间均可到达.现在出了一件极BT的事,就是八中开始闹鬼了。老大决定加强安保,现在如果在某个房间中放一个士兵,则这个房间以及所有与这个房间相连的房间都会被控制.现在

老大想知道至少要多少士兵可以控制所有房间.以及有多少种不同的方案数.

Input

第一行一个数字N,代表有N个房间,房间编号从1开始到N.N<=500000,下面将有N-1行,每行两个数,代表这两个房间相连.

Output

第一行输出至少有多少个士兵才可以控制所有房间第二行输出有多少种方案数,方案数会比较大,输出除以1032992941的余数吧.

Sample Input

6
1 2
1 3
1 5
1 4
5 6

Sample Output

2
2

HINT

第一种方案是将士兵放在1号房间及6号房间

第二种方案是将士兵放在1号房间及5号房间

Source

树形Dp

时间: 2024-12-15 01:59:21

BZOJ 2314: 士兵的放置( 树形dp )的相关文章

【BZOJ2314】士兵的放置 树形DP

[BZOJ2314]士兵的放置 Description 八中有N个房间和N-1双向通道,任意两个房间均可到达.现在出了一件极BT的事,就是八中开始闹鬼了.老大决定加强安保,现在如果在某个房间中放一个士兵,则这个房间以及所有与这个房间相连的房间都会被控制.现在 老大想知道至少要多少士兵可以控制所有房间.以及有多少种不同的方案数. Input 第一行一个数字N,代表有N个房间,房间编号从1开始到N.N<=500000,下面将有N-1行,每行两个数,代表这两个房间相连. Output 第一行输出至少有

BZOJ 2314 士兵的放置(play) 树形DP

题目大意:给定一棵树,求最小支配集以及最小支配集数量 首先我们需要会求最小支配集- - 其实支配集的求法很优雅的= = 那些第一问就写了一大坨的第二问还怎么写- - 可以自己YY一下简单的支配集求法= = 实在不懂看代码吧我懒得解释了= = 然后第二问就直接把方案数顺便统计下就行了 大半夜胡乱写了发居然也过了= = #include <cstdio> #include <cstring> #include <iostream> #include <algorith

[BZOJ 4033] [HAOI2015] T1 【树形DP】

题目链接:BZOJ - 4033 题目分析 使用树形DP,用 f[i][j] 表示在以 i 为根的子树,有 j 个黑点的最大权值. 这个权值指的是,这个子树内部的点对间距离的贡献,以及 i 和 Father[i] 之间的边对答案的贡献(比如这条边对黑点对距离和的贡献就是子树内部的黑点数 * 子树外部的黑点数 * 这条边的权值). 然后DFS来求,枚举 i 的每个儿子 j,现在的 f[i][] 是包含了 [1, j-1] 子树,然后两重循环枚举范围是 [1, j - 1] 的子树总 Size 和

bzoj 3566: [SHOI2014]概率充电器 树形DP

首先普及一个概率公式 P(A+B)=P(A)+P(B)-P(AB) 题意:一些充电元件和导线构成一棵树,充电元件是否能充电有2种情况, 1.它自己有qi%的概率充电 2.与它相邻的元件通过导线给它充电(导线有p%的概率导通) 求最终充了电的元件的期望 题解:首先可以将元件能否充电分成3种情况考虑, 1.它自己给自己充好了电 2.它的儿子方向给它传送了电 3.它的父亲方向给它传送了电. 对于1,题目已经给出可以直接赋值, 对于2,可以通过一次树的深度遍历求得.pson[now]=pson[now]

BZOJ 2878([Noi2012]迷失游乐园-树形DP+环加外向树+期望DP+vector的erase)

2878: [Noi2012]迷失游乐园 Time Limit: 10 Sec  Memory Limit: 512 MBSec  Special Judge Submit: 319  Solved: 223 [Submit][Status] Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m只可能等于n或者n-1).小Z现在所在的大门也正好是

BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )

一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. --------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm&

BZOJ 2435 道路修建 NOI2011 树形DP

一看到这道题觉得很水,打了递归树形DP后RE了一组,后来发现必须非递归(BFS) 递归版本84分: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int N,point[1000003],next[2000003],v[2000003],c[2000003],cnt=0,f[1000003]; bool p[1000003]; long long sum=0; vo

BZOJ 2286 消耗战 (虚树+树形DP)

给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<=500000) 考虑树形DP,我们令mn[i]表示i节点无法与1节点相连切除的最小权值.显然有mn[i]=min(E(fa,i),mn[fa]).大致就是i到1的简单路径上的最小边.我们对于每个询问.把询问的点不妨称为关键点.令dp[i]表示i节点不能与子树的关键点连接切掉的最小权值.那么有,如果son[i]

BZOJ 2500 幸福的道路 树形DP+单调队列

题目大意:给定一棵树,令a[i]为从第i个节点出发的最长链,求a[i]中最长的区间,满足区间内最大值与最小值之差不超过m 读错题害死人,脑残害死人 求a[i]显然是树形DP 考虑从一个点出发的链可以从子节点走,也可以从父节点走 因此我们DP两次,第一次求出从子节点走的最长链,第二次求出从父节点走的最长链,两次取max就是答案 但是直接DP会有问题,因为从父节点走的最长链可能是从自己的子树出发的,这样就会走重 因此除记录从子节点出发的最长链外还要记录一个从另一个子节点出发的次长链,如果最长链长度相