Vijos p1770 大内密探 树形DP+计数
4天终于做出来了,没错我就是这么蒟蒻。教训还是很多的。
建议大家以后编树形DP不要用记忆化搜索,回溯转移状态个人感觉更有条理性。
大神题解传送门 by iwtwiioi
我的题解大家可以看注释"//"部分
本题我用的树形DP中dp[x][fa][need]表示编号为x的节点的父亲选(1)没选(0),x的父亲需(1)不需要(0)其他节点来覆盖。
若父亲节点选了,则need肯定为0,所以不存在fa==1而need==1的状态,相当于浪费了¼的空间。毕竟数据范围比较小,而且程序要有可读性!程序要有可读性!程序要有可读性!我这么写代码不是加强了程序的可读性吗?像iwtwiioi那样用012表示状态题解和程序的可读性大大降低,大家在读题解时难免要费点劲。并没有贬义
!!!╮(╯_╰)╭

my code:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int point[],next[],v[],cnt=,N,l[],r[],pre[],con[];
const long long mo=;
long long f[][][];
int dp[][][];
bool p[];
void memsetf(){for(int i=;i<=N;++i)for(int j=;j<;++j)for (int k=;k<;++k)f[i][j][k]=;}
void insect(int x,int y){next[cnt]=point[x];point[x]=cnt;v[cnt]=y;cnt++;}
void dfs(int x)
{
if (x==) return;
int i,j=;
for (i=point[x];i!=-;i=next[i])
if (p[v[i]]==)
{
p[v[i]]=;
if (l[x]==) {l[x]=v[i];j=v[i];}
else {r[j]=v[i];pre[v[i]]=j;j=v[i];}
}
dfs(j); con[j]=con[l[j]]+;
while (pre[j]!=-){j=pre[j]; dfs(j); con[j]=con[l[j]]+con[r[j]]+;}
}
void work(int x)
{
if (r[x]!=) work(r[x]);
if (l[x]!=) work(l[x]);
long long s=; int num=;
if ((l[x]==)&&(r[x]==))
{
dp[x][][]=; dp[x][][]=; dp[x][][]=; return;
}
else
if (l[x]==)
{
dp[x][][]=+dp[r[x]][][]; f[x][][]=f[r[x]][][];
dp[x][][]=+dp[r[x]][][]; f[x][][]=f[r[x]][][];
dp[x][][]=dp[r[x]][][]; f[x][][]=f[r[x]][][];
return;
}
else
if (r[x]==)
{
dp[x][][]=+dp[l[x]][][]; f[x][][]=f[l[x]][][];
//dp[x][0][0]=min(1+dp[l[x]][1][0],dp[l[x]][0][1]);
if (+dp[l[x]][][]<dp[l[x]][][])
dp[x][][]=+dp[l[x]][][],f[x][][]=f[l[x]][][];
else
if (+dp[l[x]][][]>dp[l[x]][][])
dp[x][][]=dp[l[x]][][],f[x][][]=f[l[x]][][];
else
dp[x][][]=dp[l[x]][][],f[x][][]=(f[l[x]][][]+f[l[x]][][])%mo;
//dp[x][1][0]=min(1+dp[l[x]][1][0],dp[l[x]][0][0]);
if (+dp[l[x]][][]<dp[l[x]][][])
dp[x][][]=+dp[l[x]][][],f[x][][]=f[l[x]][][];
else
if (+dp[l[x]][][]>dp[l[x]][][])
dp[x][][]=dp[l[x]][][],f[x][][]=f[l[x]][][];
else
dp[x][][]=dp[l[x]][][],f[x][][]=(f[l[x]][][]+f[l[x]][][])%mo;
return;
}
//dp[x][0][1]=min(dp[x][0][1],dp[l[x]][0][1]+dp[r[x]][0][1]);
//dp[x][0][1]=min(dp[x][0][1],1+dp[l[x]][1][0]+dp[r[x]][0][0]);
if (dp[l[x]][][]+dp[r[x]][][]<+dp[l[x]][][]+dp[r[x]][][])
dp[x][][]=dp[l[x]][][]+dp[r[x]][][],f[x][][]=(f[l[x]][][]*f[r[x]][][])%mo;
else
if (dp[l[x]][][]+dp[r[x]][][]>+dp[l[x]][][]+dp[r[x]][][])
dp[x][][]=+dp[l[x]][][]+dp[r[x]][][],f[x][][]=(f[l[x]][][]*f[r[x]][][])%mo;
else
{
dp[x][][]=+dp[l[x]][][]+dp[r[x]][][];
f[x][][]=((f[l[x]][][]*f[r[x]][][])%mo+(f[l[x]][][]*f[r[x]][][])%mo)%mo;
}
//dp[x][0][0]=min(dp[x][0][0],dp[l[x]][0][1]+dp[r[x]][0][0]);
//dp[x][0][0]=min(dp[x][0][0],1+dp[l[x]][1][0]+dp[r[x]][0][0]);
if (dp[l[x]][][]+dp[r[x]][][]<+dp[l[x]][][]+dp[r[x]][][])
dp[x][][]=dp[l[x]][][]+dp[r[x]][][],f[x][][]=(f[l[x]][][]*f[r[x]][][])%mo;
else
if (dp[l[x]][][]+dp[r[x]][][]>+dp[l[x]][][]+dp[r[x]][][])
dp[x][][]=+dp[l[x]][][]+dp[r[x]][][],f[x][][]=(f[l[x]][][]*f[r[x]][][])%mo;
else
{
dp[x][][]=+dp[l[x]][][]+dp[r[x]][][];
f[x][][]=((f[l[x]][][]*f[r[x]][][])%mo+(f[l[x]][][]*f[r[x]][][])%mo)%mo;
}
//dp[x][1][0]=min(dp[x][1][0],dp[l[x]][0][0]+dp[r[x]][1][0]);
//dp[x][1][0]=min(dp[x][1][0],1+dp[l[x]][1][0]+dp[r[x]][1][0]);
if (dp[l[x]][][]+dp[r[x]][][]<+dp[l[x]][][]+dp[r[x]][][])
dp[x][][]=dp[l[x]][][]+dp[r[x]][][],f[x][][]=(f[l[x]][][]*(f[r[x]][][]))%mo;
else
if (dp[l[x]][][]+dp[r[x]][][]>+dp[l[x]][][]+dp[r[x]][][])
dp[x][][]=+dp[l[x]][][]+dp[r[x]][][],f[x][][]=(f[l[x]][][]*f[r[x]][][])%mo;
else
{
dp[x][][]=+dp[l[x]][][]+dp[r[x]][][];
f[x][][]=((f[l[x]][][]*(f[r[x]][][]))%mo+(f[l[x]][][]*f[r[x]][][])%mo)%mo;
}
}
int main()
{
memset(point,-,sizeof(point));
memset(next,-,sizeof(next));
memset(pre,-,sizeof(pre));
memset(dp,,sizeof(dp));
memset(v,,sizeof(v));
memset(p,,sizeof(p));
memset(l,,sizeof(l));
memset(r,,sizeof(r));
scanf("%d\n",&N);
memsetf();
int i,x,y;
for (i=;i<N;++i)
{
scanf("%d %d\n",&x,&y);
insect(x,y);insect(y,x);
}p[]=;dfs();
work(l[]);
if (dp[l[]][][]<(+dp[l[]][][]))
printf("%d\n%I64d\n",dp[l[]][][],f[l[]][][]);
else
if (dp[l[]][][]>(+dp[l[]][][]))
printf("%d\n%I64d\n",+dp[l[]][][],f[l[]][][]);
else
printf("%d\n%I64d\n",+dp[l[]][][],(f[l[]][][]+f[l[]][][])%mo);
return ;
}
背景
大内密探,负责秘密保护皇上,还有保护皇宫内外一切产业。——大内密探零零七
描述
在古老的皇宫中,有N个房间以及N-1条双向通道,每条通道连接着两个不同的房间,所有的房间都能互相到达。皇宫中有许多的宝物,所以需要若干个大内密探来守护。一个房间被守护当切仅当该房间内有一名大内密探或者与该房间直接相邻的房间内有大内密探。
现在身为大内密探零零七的你想知道要把整个皇宫守护好至少需要多少名大内密探以及有多少种安排密探的方案。两种方案不同当且仅当某个房间在一种方案有密探而在另一个方案内没有密探。
格式
输入格式
第一行一个正整数N.(1<=N<=100000)
后面N-1行,每行两个正整数a和b,表示房间a和房间b之间有一条无向通道。
房间的编号从1到N
输出格式
第一行输出正整数K,表示最少安排的大内密探。
第二行输出整数S,表示有多少种方案安排最少的密探,由于结果可能较大,请输出方案数mod 1000000007的余数。
限制
每个测试点1s
提示
30%保证:n <= 10
70%保证:n <= 1000
100%保证:n <= 100000
Vijos p1770 大内密探 树形DP+计数的更多相关文章
- Vijos p1518河流 树形DP
https://vijos.org/p/1518 这题代码我基本是抄的,实在太难想了.但是也学到了一些东西. 比如:多叉树转二叉树存,这个细细一想,确实使得在dfs的时候,实现起来方便很多. 说一说具 ...
- vijos 1180 选课 树形DP
描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修了这M门课并考核通过就能获得 ...
- Codeforces Round #277 (Div. 2)D(树形DP计数类)
D. Valid Sets time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- 【vijos】1770 大内密探(树形dp+计数)
https://vijos.org/p/1770 不重不漏地设计状态才能正确的计数QAQ 虽然可能最优化是正确的,但是不能保证状态不相交就是作死.... 之前设的状态错了... 应该设 f[i][0] ...
- Vijos p1892 树上的最大匹配 树形DP+计数 被卡常我有特殊技巧heheda
https://vijos.org/p/1892 此题需要手动开栈: <<; //256MB char *p=(char*)malloc(size)+size; __asm__(" ...
- 【vijos】1892 树上的最大匹配(树形dp+计数)
https://vijos.org/p/1892 这个必须得卡评测机+手动开栈才能卡过QAQ 手动开栈我百度的... int size=256<<20; //256MB char *p=( ...
- Tree Cutting (Hard Version) CodeForces - 1118F2 (树形DP,计数)
大意:给定树, 每个点有颜色, 一个合法的边集要满足删除这些边后, 每个连通块内颜色仅有一种, 求所有合法边集的个数 $f[x][0/1]$表示子树$x$中是否还有与$x$连通的颜色 对于每种颜色已经 ...
- 牛客第八场 C-counting paths 树形dp计数
题目地址 题意 给你一颗树 初始点颜色全部为白色 对于每一个满足要求一的点集s f(s)的定义为先把点集内的点染黑 满足要求二的路径集合数量 要求一为两两黑点之间不能出现白色的点 要求二为将这个路径集 ...
- 『树上匹配 树形dp』
树上匹配 Description 懒惰的温温今天上班也在偷懒.盯着窗外发呆的温温发现,透过窗户正巧能看到一棵 n 个节点的树.一棵 n 个节点的树包含 n-1 条边,且 n 个节点是联通的.树上两点之 ...
随机推荐
- 分享一个解决MySQL写入中文乱码的方法
分享一个解决MySQL写入中文乱码的方法 之前有发帖请教过如何解决MySQL写入中文乱码的问题.但没人会,或者是会的人不想回答.搜索网上的答案并尝试很多次无效,所以当时就因为这个乱码问题搁浅了一个软件 ...
- 翻译《Writing Idiomatic Python》(二):函数、异常
原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...
- UESTC 900 方老师炸弹 --Tarjan求割点及删点后连通分量数
Tarjan算法. 1.若u为根,且度大于1,则为割点 2.若u不为根,如果low[v]>=dfn[u],则u为割点(出现重边时可能导致等号,要判重边) 3.若low[v]>dfn[u], ...
- 关于JAVA应用中文字体显示小方框的问题解决
最近碰到linux下jboss应用中中文字体显示为小方框: “在JRE 5以上的java环境中,java会自动加载$JAVA_HOME/jre/lib/fonts目录下的字体.链接或复制宋体或微软雅黑 ...
- Jira-Clone与发邮件的使用
1.克隆问题 包括两部分,先进行Clone,再进行移动 a.选择要克隆的问题,点击More Actions-Clone,在弹出框“复制问题”中,点击“创建”按钮即克隆成功 b.移动问题,点击More ...
- 判断一个值是否在数组里,可以检测数字,字符串,json对象
Array.prototype.indexOf = function (val) {//判断数组是否存在某个值,如果存在返回该值对应的索引,否则返回-1 for (var i = 0; i < ...
- 判断变量是否为json对象
var m ={a:'A'}; if(typeof m == 'object' && JSON.stringify(m).indexOf('{') == 0){//判断变量m是不是js ...
- 后台首页品字形(frameset)框架搭建
get_defined_constants([true])//显示所有常量信息.参数true,表示分组显示,查看当前系统给我提供了哪些常量可以使用,包括自定义常量. __CONTROLLER__//获 ...
- setAttribute改变属性,动态改变类
<style type="text/css"> .box{color:red;} </style> <div>通过setAttribute添加d ...
- 【夯实Mysql基础】MySQL在Linux系统下配置文件及日志详解
本文地址 分享提纲: 1. 概述 2. 详解配置文件 3. 详解日志 1.概述 MySQL配置文件在Windows下叫my.ini,在MySQL的安装根目录下:在Linux下叫my.cnf,该文件位于 ...