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 个节点是联通的.树上两点之 ...
随机推荐
- LeetCode题解-----First Missing Positive
Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2,0] ...
- 边工作边刷题:70天一遍leetcode: day 84-3
Meeting Rooms I/II 要点:这题和skyline类似,利用了interval start有序的特点,从左向右处理,用一个heap来动态表示当前占用rooms的时间段,所以heap的si ...
- extern "C" 用法解析
extern "c"用法解析 作者 作者Jason Ding ,链接http://www.jianshu.com/p/5d2eeeb93590 引言 C++保留了一部分过程式语言的 ...
- codeforces gym-101078
题目链接: http://codeforces.com/gym/101078 A: #include <iostream> #include <cstdio> #include ...
- ZOJ 3157 Weapon --计算几何+树状数组
题意:给一些直线,问这些直线在直线x=L,x=R之间有多少个交点. 讲解见此文:http://blog.sina.com.cn/s/blog_778e7c6e0100q64a.html 首先将直线分别 ...
- POJ 2823 Sliding Window 再探单调队列
重新刷这个经典题,感觉跟以前不一样了,变得更加容易理解了,不讲解了,看代码.注意:要用C++提交,用G++会超时.. 代码: #include <iostream> #include &l ...
- Spring 一二事(5) - 依赖注入
<!-- 依赖注入的装配过程 --> <bean id="person" class="com.lee.spring007.di.xml.setter. ...
- JMeter学习(三十二)属性和变量
一.Jmeter中的属性: 1.JMeter属性统一定义在jmeter.properties文件中,我们可以在该文件中添加自定义的属性 2.JMeter属性在测试脚本的任何地方都是可见的(全局),通常 ...
- 书籍推荐 《移动Web手册》 奇舞团
书籍推荐 <移动Web手册> 奇舞团
- js fs read json 文件json字符串无法解析
读取 xxx.txt(里面就是一段 json)-> JSON.parse( fs.readFileSync( xxx.txt ) ) -> 报 SyntaxError: unexpecte ...