[vijos 1770]大内密探
描述
在古老的皇宫中,有N个房间以及N-1条双向通道,每条通道连接着两个不同的房间,所有的房间都能互相到达。皇宫中有许多的宝物,所以需要若干个大内密探来守护。一个房间被守护当切仅当该房间内有一名大内密探或者与该房间直接相邻的房间内有大内密探。
现在身为大内密探零零七的你想知道要把整个皇宫守护好至少需要多少名大内密探以及有多少种安排密探的方案。两种方案不同当且仅当某个房间在一种方案有密探而在另一个方案内没有密探。
格式
输入格式
第一行一个正整数N.(1<=N<=100000)
后面N-1行,每行两个正整数a和b,表示房间a和房间b之间有一条无向通道。
房间的编号从1到N
输出格式
第一行输出正整数K,表示最少安排的大内密探。
第二行输出整数S,表示有多少种方案安排最少的密探,由于结果可能较大,请输出方案数mod 1000000007的余数。
样例1
样例输入1[复制]
7
2 1
3 1
4 2
5 1
6 2
7 6
样例输出1[复制]
3
4
首先这是两个子问题
第一问是比较基本的树形dp
设
f[i][0] i的子树中,i被覆盖但不取i的方案数
f[i][1] i被覆盖,没有其他限制的方案数
f[i][2] i点不取且i不被儿子覆盖的方案数
第二问 g[i][0~3]表示上面三个对应的方案数
第一问的转移
然后为了方便g的计算,我们一会再讨论f[i][0]的转移
那么如何来搞这个g呢。。
首先g[i][1,2]随便加法乘法原理算算就好了,但是g[i][0]比较蛋疼
首先一般我们会这样算f[i][0]
这样会在转移g的时候出现重复状态
然后我们发现可以对后面一坨维护一下前缀和和后缀和避免重复
实现细节看代码
#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<complex>
#include<iostream>
#include<assert.h>
#include<algorithm>
using namespace std;
using namespace std;
#define pb push_back
#define inf 1001001001
#define infll 1001001001001001001LL
#define FOR0(i,n) for(int (i)=0;(i)<(n);++(i))
#define FOR1(i,n) for(int (i)=1;(i)<=(n);++(i))
#define mp make_pair
#define pii pair<int,int>
#define ll long long
#define ld double
#define vi vector<int>
#define SZ(x) ((int)((x).size()))
#define fi first
#define se second
#define RI(n) int (n); scanf("%d",&(n));
#define RI2(n,m) int (n),(m); scanf("%d %d",&(n),&(m));
#define RI3(n,m,k) int (n),(m),(k); scanf("%d %d %d",&(n),&(m),&(k));
template<typename T,typename TT> ostream& operator<<(ostream &s,pair<T,TT> t) {return s<<"("<<t.first<<","<<t.second<<")";}
template<typename T> ostream& operator<<(ostream &s,vector<T> t){FOR0(i,sz(t))s<<t[i]<<" ";return s; }
#define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl
#define all(t) t.begin(),t.end()
#define FEACH(i,t) for (typeof(t.begin()) i=t.begin(); i!=t.end(); i++)
#define TESTS RI(testow)while(testow--)
#define FORZ(i,a,b) for(int (i)=(a);(i)<=(b);++i)
#define FORD(i,a,b) for(int (i)=(a); (i)>=(b);--i)
#define gmax(a,b) (a)=max((a),(b))
#define gmin(a,b) (a)=min((a),(b))
#define ios0 ios_base::sync_with_stdio(0)
#define Ri register int
#define gc getchar()
#define il inline
il int read(){
bool f=true;
Ri x=0;char ch;
while(!isdigit(ch=gc))
if(ch=='-')f=false;
while(isdigit(ch)){
x=(x<<1)+(x<<3)+ch-'0';
ch=gc;
}
return f?x:-x;
}
#define gi read()
#define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
#define childs(x,i) for(int i=last[x]; i; i=e[i].next)
const int N=100005,mod=1000000007;
int last[N],cnt,n,l,f[N][3],r[N],st[N];
ll d[N][3],suml,sumr[N];
struct edge{
int to,next;
}e[230000];
ll mul(ll a,ll b){
return ((a%mod)*(b%mod))%mod;
}
ll Plus(ll a,ll b){
return (a%mod+b%mod)%mod;
}
void insert(int u, int v) {
e[++cnt].next=last[u];last[u]=cnt;e[cnt].to=v;
e[++cnt].next=last[v];last[v]=cnt;e[cnt].to=u;
} void dfs(int x,int fa) {
int t1=1,t2=0,s1=1,s2=1,ch;
childs(x,i)
if((ch=e[i].to)!=fa) {
ll T=0;
dfs(ch,x);
int mn=min(min(f[ch][0],f[ch][1]),f[ch][2]);
FOR0(j,3)
if(f[ch][j]==mn) T+=d[ch][j];
s1=mul(s1,T);
T=0;
s2=mul(s2,d[ch][0]);
t1+=mn;
t2+=f[ch][0];
}
f[x][1]=t1;
f[x][2]=t2;
d[x][1]=s1;
d[x][2]=s2;
int sz=0;
childs(x,i) if(e[i].to!=fa) st[++sz]=e[i].to;
r[sz+1]=0;
sumr[sz+1]=1;suml=1;l=0;
FORD(i,sz,1) {
ch=st[i];
ll T=0;
int mn=min(f[ch][0],f[ch][1]);
FOR0(j,2)if(f[ch][j]==mn) T+=d[ch][j];
r[i]=r[i+1]+mn;
sumr[i]=mul(sumr[i+1],T);
}
f[x][0]=N;
FOR1(i,sz){
int fyb=l+f[st[i]][1]+r[i+1];
if(fyb<f[x][0]) f[x][0]=fyb,d[x][0]=mul(d[st[i]][1],mul(suml,sumr[i+1]));
else if(fyb==f[x][0]) d[x][0]=Plus(d[x][0],mul(d[st[i]][1],mul(suml,sumr[i+1])));
if(f[st[i]][0]==N) break;
l+=f[st[i]][0];
suml=mul(suml,d[st[i]][0]);
}
}
int main() {
RI(n);
FOR1(i,n-1)
insert(gi,gi);
int root=1;
dfs(root,-1);
int ans1=min(f[root][1],f[root][0]),ans2=0;
if(ans1==f[root][0])
ans2=Plus(ans2,d[root][0]);
if(ans1==f[root][1])
ans2=Plus(ans2,d[root][1]);
printf("%d\n%d\n",ans1,ans2);
return 0;
}
[vijos 1770]大内密探的更多相关文章
- 【vijos】1770 大内密探(树形dp+计数)
https://vijos.org/p/1770 不重不漏地设计状态才能正确的计数QAQ 虽然可能最优化是正确的,但是不能保证状态不相交就是作死.... 之前设的状态错了... 应该设 f[i][0] ...
- Vijos p1770 大内密探 树形DP+计数
4天终于做出来了,没错我就是这么蒟蒻.教训还是很多的. 建议大家以后编树形DP不要用记忆化搜索,回溯转移状态个人感觉更有条理性. 大神题解传送门 by iwtwiioi 我的题解大家可以看注释&quo ...
- 【BZOJ 1061】【Vijos 1825】【NOI 2008】志愿者招募
http://www.lydsy.com/JudgeOnline/problem.php?id=1061 https://vijos.org/p/1825 直接上姜爷论文... #include< ...
- vijos P1915 解方程 加强版
背景 B酱为NOIP 2014出了一道有趣的题目, 可是在NOIP现场, B酱发现数据规模给错了, 他很伤心, 哭得很可怜..... 为了安慰可怜的B酱, vijos刻意挂出来了真实的题目! 描述 已 ...
- vijos P1780 【NOIP2012】 开车旅行
描述 小\(A\)和小\(B\)决定利用假期外出旅行,他们将想去的城市从\(1\)到\(N\)编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市\(i\)的海拔高度为 ...
- 【BZOJ 2541】【Vijos 1366】【CTSC 2000】冰原探险
http://www.lydsy.com/JudgeOnline/problem.php?id=2541 https://vijos.org/p/1366 loli秘制大爆搜_(:з」∠)_坑了好久啊 ...
- 【BZOJ 1065】【Vijos 1826】【NOI 2008】奥运物流
http://www.lydsy.com/JudgeOnline/problem.php?id=1065 https://vijos.org/p/1826 好难的题啊TWT ∈我这辈子也想不出来系列~ ...
- BZOJ 1770: [Usaco2009 Nov]lights 燈
Description 一个图,对一个点进行操作会改变这个点及其相邻的点的状态,问全部变成黑色至少需要几次.数据保证有解. Sol Meet in middle. 我一开始写个高斯消元,发现有两个点过 ...
- [题解]vijos & codevs 能量项链
a { text-decoration: none; font-family: "comic sans ms" } .math { color: gray; font-family ...
随机推荐
- php面向对象的多态
多态是指使用类的上下文来重新定义或改变类的性质或行为,或者说接口的多种不同的实现方式即为多态.把不同的子类对象都当成父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需要 ...
- jQuery骨架
jQuery选择器 jQuery操作DOM jQuery中的事件与应用 jQuery的动画与特效 Ajax在jQuery中的应用 jQuery常用插件 jQuery UI插件 jQuery实用工具函数 ...
- 走出 null 就是空值的误区,以及变量赋值原理
先放一张图片作为引入: 这里我用了一个示意图作为讲解: 平时,我们写的变量为什么能在我们调用它的时候就能被我们拿到所用,跟存钱罐一样,你往里面存一元大洋,它里面就有一元大洋,那么我们的变量在被我们创建 ...
- 2016.10.30 济南学习 Day2 下午 T1
他 [问题描述] 一张长度为N的纸带,我们可以从左至右编号为0 − N(纸带最左端标号为 0).现在有M次操作,每次将纸带沿着某个位置进行折叠,问所有操作之后纸带 的长度是多少. [输入格式] 第一行 ...
- 使用winform来递归实现资源管理器
这里主要是对TreeView控件的学习 所使用到的方法: string path=@"E:\歌词"; //获得指定文件夹下所有文件夹的名称,这是带路径的,如:E:\歌词\11111 ...
- webpack使用webpack-dev-middleware进行热重载
新手,刚开始学习webpack,想使用webdevserver,但定制性太差,于是研究了一下使用webpack-dev-middleware进行指定. 根据文档https://www.npmjs.co ...
- php中json_encode中文编码问题分析
众所周知使用json_encode可以方便快捷地将对象进行json编码,但是如果对象的属性中存在着中文,问题也就随之而来了.json_encode会将中文转换为unicode编码例如:'胥'经过jso ...
- 集成环境wamp环境下 memcached的安装
早就听说过memcached,但是一直没实践过.所有今天有时间就搞了一下,哎废了我一上午才搞定!一上午啊,好丢人.特写记录一下 先说一下我遇到的问题:按照别人教程(还有好多)说的,安装后没有任何的错误 ...
- java dom4j解析xml用到的几个方法
1. 读取并解析XML文档: SAXReader reader = new SAXReader(); Document document = reader.read(new File(fileName ...
- Microsoft Azure 全球状态
除了mooncake的中国大陆区域 Azure status http://azure.microsoft.com/en-us/status/?rnd=1#current http://azure.m ...