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 定时备份数据库
每天零点备份一次数据库,备份文件放在指定目录(如果目录不存在则新建),按月存储: 将下面这段命令存储为一个 *.bat 文件,添加一个Windows任务计划程序(Task scheduler)指向这个 ...
- readonly与const
readonly与const 在C#中,readonly 与 const 都是定义常量,但不同之处在于:readonly 是运行时常量,而 const 是编译时常量. ; public void Te ...
- UESTC 1227 & POJ 3667 Hotel
非常细腻的线段树题目啊,后来还是有个细节写错了,查了一个晚上..就不分析了. 代码: #include <iostream> #include <cstdio> #includ ...
- 第51课 C++对象模型分析(下)
1. 单继承对象模型 (1)单一继承 [编程实验]继承对象模型初探 #include <iostream> using namespace std; class Demo { protec ...
- github结合TortoiseGit使用sshkey,无需输入账号和密码
1.github上支持三种方式进行项目的clone https,ssh,subversion https://github.com/用户名/版本库.git ssh的方式 git@github.c ...
- Android 中JNI创建实例
参考文档: http://blog.sina.com.cn/s/blog_a11f64590101924l.html http://www.cnblogs.com/hoys/archive/2010/ ...
- HTML5和css3的总结四
HTML5的新东西总结四: 1>video和audio 声明方法(可以制作背景音乐) var oV/oA=new Video()/Audio(); oV/oA.src=''; oV/oA.pla ...
- where,having与 group by连用的区别
select 列a,聚合函数 from 表名 where 过滤条件 group by 列a having 过滤条件 group by 字句也和where条件语句结合在一起使用.当结合在一起时,wher ...
- canvas模仿微信抢红包功能
1.原理:先创建一张img图片,用filter滤镜制作毛玻璃效果. 2.利用绝对定位,使canvas刚好盖在img上面. 3.利用canvas原生clip函数剪辑一个圆形. 地址:http://san ...
- poj 1411 Calling Extraterrestrial Intelligence Again(超时)
Calling Extraterrestrial Intelligence Again Time Limit: 1000MS Memory Limit: 65536K Total Submissi ...