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 个节点是联通的.树上两点之 ...
随机推荐
- dipole antenna simulation by HFSS
工作频点为1GHz,新建工程,添加新设计,编辑添加下面的变量 建立天线模型,即两个金属圆柱.编辑完一个振子后,另一半可以用镜像命令产生参数如下设置 ,材料为PEC 两个圆柱间建立一个矩形片,连接两个圆 ...
- 每日学习心得:UEditor样式被过滤无法显示问题
前言: 上周开发中有用到开源的富文本编辑器UEditor,在使用的过程中遇到了样式被过滤无法显示问题,经过一番折腾终解决,此外,还有一些关于获取前台界面元素的一些总结. 1. UEditor样式被过滤 ...
- Java语法基础(三)----选择结构的if语句、switch语句
[前言] 流程控制语句: 在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的.也就是说程序的流程对运行结果有直接的影响.所以,我们必须清楚每条语句的执行流程.而且,很多时候我们要通过 ...
- Unity2D Sprite Packer用法介绍
想充分利用图片空间? 我们用来做sprite的图片通常会留有很多空白的地方,我们在画完了sprite之后,这些地方很可能就没有什么作用了. 如果想避免这些资源上的浪费,我们可以把各个sprite做成图 ...
- $apply方法的作用
$apply方法是用来触发脏检查,它在控制器里监听一个变量,每当这个变量的值改变的时候,它会去与最初的值做一次比较,然后HTML页面就会及时更新该变量的值(将最新的值赋值到html页面的view层或M ...
- 【转】【Asp.Net】Asp.net发送邮件的两种方法小结
这几天看了一下Asp.net发送邮件方面的东西,记得之前的IIS6上有SMTP服务器,可以直接利用这个进行邮件发送,现在的开发环境是Windows 7,找了半天没有找到,到网络上查了才知道原来wind ...
- Unity小知识
这些是我在开发时遇到的一些问题: 2D的碰撞器和3D的碰撞器是没有任何物理反应的,必须是2D对2D,3D对3D 碰撞器Collision包含触发物体的速度等信息,触发器没有
- The ServiceClass object does not implement the required method in the following form: OMElement sayHello(OMElement e)
今天遇到一件诡异的事情,打好的同一个aar包,丢到测试环境tomcat,使用soapui测试,正常反馈结果. 丢到本地tomcat,使用soapui测试,始终报以下错误. <soapenv:En ...
- C# winform 上传文件到服务器
1.首先要在服务器端新建一个网站axpx页 然后再网站的后台写代码获取winform传过来的文件名. 声明:这个方法虽然最简单最省事,但是上传大文件可能会报错,我的机器是10M, 超过10M就会提示报 ...
- openssl知识点总结
openssl知识点总结 实践总结见之前博客:http://www.cnblogs.com/Jclemo/p/6091201.html 简介 openssl是一个功能丰富且自包含的开源安全工具箱.它提 ...